// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
// see COPYRIGHT for reuse legalities
//

#import "WWEveParser.h"
#include <stdlib.h>
#import <ri/ri.h>
#import <ctype.h>
#import <strings.h>

#import "WWTCLKit.h"

#import "WWSceneClock.h"

#import <WW3DShape.h>
#import <WW3DLight.h>
#import <WW3DShader.h>
#import <RIBCommand.h>
#import <RIBAttribute.h>
#import <RIBAttributeBegin.h>
#import <RIBAttributeEnd.h>
#import <RIBArchiveRecord.h>
#import <RIBBasis.h>
#import <RIBCone.h>
#import <RIBColor.h>
#import <RIBConcatTransform.h>
#import <RIBCylinder.h>
#import <RIBDeclare.h>
#import <RIBDisk.h>
#import <RIBGeneralPolygon.h>
#import <RIBHyperboloid.h>
#import <RIBIdentity.h>
#import <RIBIlluminate.h>
#import <RIBMakeTexture.h>
#import <RIBMotionBegin.h>
#import <RIBMotionEnd.h>
#import <RIBNuPatch.h>
#import <RIBObjectInstance.h>
#import <RIBOpacity.h>
#import <RIBOption.h>
#import <RIBParaboloid.h>
#import <RIBPatch.h>
#import <RIBPatchMesh.h>
#import <RIBPerspective.h>
#import <RIBPointsGeneralPolygons.h>
#import <RIBPointsPolygons.h>
#import <RIBPolygon.h>
#import <RIBRotate.h>
#import <RIBScale.h>
#import <RIBShadingRate.h>
#import <RIBSides.h>
#import <RIBSkew.h>
#import <RIBSolidBegin.h>
#import <RIBSolidEnd.h>
#import <RIBSphere.h>
#import <RIBTextureCoordinates.h>
#import <RIBTorus.h>
#import <RIBTransform.h>
#import <RIBTransformBegin.h>
#import <RIBTransformEnd.h>
#import <RIBTranslate.h>
#import <RIBTrimCurve.h>
#import <RIBCommandList.h>
#import <EveCommand.h>
#import <EveProc.h>
#import <WWInterp.h>
#import <WWSet.h>
#import <WW3DText.h>
#import <WW3DSquishySphere.h>
#import "WWSampleGeneratorInfo.h"
#import "WWArticulatedVariableBehavior.h"

// for WWSceneClock protocol:
#import <WW3DWell.h>

#import <apps/InterfaceBuilder.h>

@implementation WWEveParser

static char errBuf[1024]; 

+ initialize {  [WWEveParser setVersion:6]; return self; }

int
massageRIB(interp, inName, outName)
Tcl_Interp  *interp; 
char        *inName, *outName;
{
  FILE  *in, *out;
  int   c, c2, quoteCount = 0, commentQuote = 0;

  /* at this point, we want to massage the rib file so that it becomes */
  /* interpretable by a rib-extended tcl interp. */
  /* we're assuming that this file has been run through catrib, so it doesn't have */
  /* any leading spaces in front of valid commands, and that it is only ASCII. */

  in = fopen(inName, "r");
  if (in == NULL)
  {  sprintf(errBuf, "unable to open RIB file named <%s>\n", inName);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }

  out = fopen(outName, "w");
  if (out == NULL)
  {  sprintf(errBuf, "unable to open output file %s\n", outName); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  
  while ((c = getc(in)) != EOF)
  {  if ((c == '\n') || (c =='
')) // need to check for ctrl-Ms...
     {  quoteCount = 0;
        c = getc(in);
        /* we want to spin until we get a character.  */
        /* -  If it's a letter, we assume that the next line contains a new command */
        /* -  It's it's anything else, we assume that last line is being continued */
	while ( (c != EOF)  && (isspace(c))) {c = getc(in); }
        if (   (c == '\"') || (c == '[') || (c == ']')  
            || (c == '1')  || (c == '2') || (c == '3') || (c == '4') || (c == '5')
            || (c == '6')  || (c == '7') || (c == '8') || (c == '9') || (c == '0')
            || (c == '-')
           )
        {  if (c == '\"')
           {  quoteCount++;
 	   }
           if (c != ']')
           {  putc(' ', out);
 	   }
        }
        else
        {  putc('\n', out);
        }
        if (c == '#')
	{  c2 = getc(in);
           if (c2 == '\n') /* short spacer comment */
           {  fprintf(out, "; ArchiveRecord comment ");
              /* let's pretend this didn't happen and drop through...*/
              c = c2;
	   } 
           else
           {  if (c2 == '#') /* it's a structure hint */
	      {  /* start with semi-colon in case it's in-line... */
		 fprintf(out, "; ArchiveRecord structure ");
	      }
              else
	      {  fprintf(out, "; ArchiveRecord comment %c", c2);
	      }
 	   }
           /* either way, spin through until we get to EOF or \n */
           commentQuote = 0;
           while ((c != EOF) && (c != '\n'))
           {  c = getc(in);
              if ((c == '{') || (c == '}'))  // need to quote these guys so tcl doesn't flip out
              {  putc('\\', out);
              }
              if (c == '\"')
              {  if (commentQuote)
                 {  putc(' ', out);
                    commentQuote = 0;
                 }  
                 else  
                 {  commentQuote = 1;
                 }  
              }
              putc(c, out);
           }
        }
        else
        {  if (c != EOF)
           {  /* might be a [ or ]... */
              if (c == '[')
              {  fprintf(out, " {");
	      }
              else
              {  if (c == ']')
                 {  fprintf(out, "} ");
	         }
	         else
                 {  putc(c, out);
	         }
	      }
	   }
        }
     }
     else /* we're not at a new-line */
     {  if (c == '[')  /* need to turn things like foo["bar into foo {bar */
        {  putc(' ', out);
           putc('{', out);
           c2 = getc(in); /* if it's a ", eat it, otherwise pass it through */
           if (c2 == ' ') /* one more try - if it's a space, eat it and try again */
           {  putc(' ', out);
              c2 = getc(in);
           }
           if (c2 != '"')
           {  ungetc(c2, in);
           }
           else
           {  quoteCount++;
           } 
        }
        else
        {  if (c == ']')
           {  putc('}', out);
              putc(' ', out);
           }
           else
           {  if (c == '"')
              {  quoteCount++;
                 c2 = getc(in);
                 if (c2 == ' ')  /* one more chance... */
		 {  c2 = getc(in);
		 }
                 if (c2 != ']')
                 {  ungetc(c2, in);
                    if ((quoteCount % 2)) /* if it's an odd number, just put out <">, if it's even put out <" > */
                    {  putc('\"', out);
		    }
                    else
                    {  fprintf(out, "\" ");
		    }
                 }
                 else
                 {  putc('}', out);
                    putc(' ', out);
                 }
              }
              else
              {  if (c == '#')
		 {  c2 = getc(in);
                    if (c2 == '\n') /* short spacer comment */
                    {  fprintf(out, "; ArchiveRecord comment ");
                       /* let's pretend this didn't happen and drop through...*/
                       c = c2;
		    } 
		    else
                    {  if (c2 == '#') /* it's just a comment */
		       {  /* start with semi-colon in case it's in-line... */
                          fprintf(out, "; ArchiveRecord structure ");
		       }
                       else
		       {  fprintf(out, "; ArchiveRecord comment %c", c2);
		       }
 		    }
                    /* either way, spin through until we get to EOF or \n */
                    while ((c != EOF) && (c != '\n'))
                    {  c = getc(in);
                       if ((c == '{') || (c == '}'))  // need to quote these guys so tcl doesn't flip out
		       {  putc('\\', out);
                       }
                       if (c == '\"')
                       {  if (commentQuote)
                          {  putc(' ', out);
                             commentQuote = 0;
                          }  
                          else  
                          {  commentQuote = 1;
                          }  
                       }
                       putc(c, out);
                    }
		 }
                 else
                 {  putc(c, out);
		 }
              }
	   }
        }
    }
  }

  fclose(in);
  fclose(out);

  return 1;
}


RtPointer
encodeFloatRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc = 0, i;
  RtFloat  *retValue, *retPtr;
  char     **argv;


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "encodeFloatRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % n)
  {  sprintf(errBuf, "encodeFloatRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retValue = (RtFloat *)malloc(argc * sizeof(RtFloat));
  if (!retValue)
  {  sprintf(errBuf, "encodeFloatRIBVar : unable to malloc memory to encode float RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retPtr = retValue;
  for (i = 0; i < argc; i ++)
  {  *retPtr++ = (RtFloat)atof(argv[i]);
  }
  free(argv);

  list_put(me->rib_parm_list, retValue);

  return (RtPointer)retValue;
}


RtPointer
encodeIntegerRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int    argc, i;
  RtInt  *retValue, *retPtr;
  char   **argv;


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "encodeIntegerRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % n)
  {  sprintf(errBuf, "encodeIntegerRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retValue = (RtInt *)malloc(argc * sizeof(RtInt));
  if (!retValue)
  {  sprintf(errBuf, "encodeIntegerRIBVar : unable to malloc memory to encode int RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retPtr = retValue;
  for (i = 0; i < argc; i ++)
  {  *retPtr++ = (RtInt)atoi(argv[i]);
  }
  free(argv);

  list_put(me->rib_parm_list, retValue);

  return (RtPointer)retValue;
}


RtPointer
encodeStringRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  char  **retValue;
  int   howMany = 1 + strlen(parm);


  retValue = (char **)malloc(sizeof(char *));
  if (!retValue)
  {  sprintf(errBuf, "encodeStringRIBVar : unable to malloc memory to encode string RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  *retValue = (char *)malloc(howMany);
  if (!*retValue)
  {  sprintf(errBuf, "encodeStringRIBVar : unable to malloc memory to encode string RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  strcpy(*retValue, parm);

  list_put(me->rib_parm_list, retValue);
 
  // I used to think this is right, but experience with the RIB client library tells me differently...
  // return (RtPointer)(retValue);
  // No, I was right the first time.  For the client library, the above is correct.
  // for the actual prman/qrman library, passing the address is right... (sigh)
  // 
  return (RtPointer)(retValue);
}


RtPointer
encodePointRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc, i;
  RtPoint  *retValue, *retPtr;
  char     **argv;


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "encodePointRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "encodePointRIBVar : expected parameter to be in groups of %d", (n*3));
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retValue = (RtPoint *)malloc((argc/3) * sizeof(RtPoint));
  if (!retValue)
  {  sprintf(errBuf, "encodePointRIBVar : unable to malloc memory to encode point RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retPtr = retValue;
  for (i = 0; i < argc; i += 3)
  {  (*retPtr)[0] = (RtFloat)atof(argv[i+0]);
     (*retPtr)[1] = (RtFloat)atof(argv[i+1]);
     (*retPtr)[2] = (RtFloat)atof(argv[i+2]);
     retPtr++;
  }
  free(argv);

  list_put(me->rib_parm_list, retValue);

  return (RtPointer)retValue;
}


RtPointer
encodeColorRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc, i;
  RtColor  *retValue, *retPtr;
  char     **argv;


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "encodeColorRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "encodeColorRIBVar : expected parameter to be in groups of %d", (n*3));
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retValue = (RtColor *)malloc((argc/3) * sizeof(RtColor));
  if (!retValue)
  {  sprintf(errBuf, "encodeColorRIBVar : unable to malloc memory to encode color RIB variable");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  retPtr = retValue;
  for (i = 0; i < argc; i += 3)
  {  (*retPtr)[0] = (RtFloat)atof(argv[i+0]);
     (*retPtr)[1] = (RtFloat)atof(argv[i+1]);
     (*retPtr)[2] = (RtFloat)atof(argv[i+2]);
     retPtr++;
  }
  free(argv);

  list_put(me->rib_parm_list, retValue);

  return (RtPointer)retValue;
}


char
*archiveFloatRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc;
  char     **argv, archiveInfo[256];


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "archiveFloatRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % n)
  {  sprintf(errBuf, "archiveFloatRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  free(argv);
  sprintf(archiveInfo, "[%df]", argc);
  return (char *)NXCopyStringBuffer(archiveInfo);
}


char
*archiveIntegerRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int    argc;
  char   **argv, archiveInfo[256];


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "archiveIntegerRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % n)
  {  sprintf(errBuf, "archiveIntegerRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  free(argv);
  sprintf(archiveInfo, "[%di]", argc);
  return (char *)NXCopyStringBuffer(archiveInfo);
}


char
*archiveStringRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  return (char *)NXCopyStringBuffer("*");
}


char 
*archivePointRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc;
  char     **argv, archiveInfo[256];


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "archivePointRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "archivePointRIBVar : expected parameter to be in groups of %d", (n*3));
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  free(argv);
  sprintf(archiveInfo, "[%df]", argc);
  return (char *)NXCopyStringBuffer(archiveInfo);
}


char
*archiveColorRIBVar(me, interp, parm, n)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
{
  int      argc;
  char     **argv, archiveInfo[256];


  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "archiveColorRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return RI_NULL;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "archiveColorRIBVar : expected parameter to be in groups of %d", (n*3));
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return RI_NULL;
  }
  free(argv);
  sprintf(archiveInfo, "[%df]", argc);
  return (char *)NXCopyStringBuffer(archiveInfo);
}


int
printfFloatRIBVar(me, interp, parm, n, typeInfoPtr)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
int   *typeInfoPtr;
{
  int      argc;
  char     **argv;


  *typeInfoPtr = WW_FLOAT;
  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "printfFloatRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  if (argc % n)
  {  sprintf(errBuf, "printfFloatRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return argc;
  }
  free(argv);
  return argc;
}


int
printfIntegerRIBVar(me, interp, parm, n, typeInfoPtr)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
int   *typeInfoPtr;
{
  int      argc;
  char     **argv;


  *typeInfoPtr = WW_INT;
  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "printfIntegerRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  if (argc % n)
  {  sprintf(errBuf, "printfIntRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return argc;
  }
  free(argv);
  return argc;
}


int
printfStringRIBVar(me, interp, parm, n, typeInfoPtr)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
int   *typeInfoPtr;
{
  *typeInfoPtr = WW_STRING;
  return 1;
}


int
printfColorRIBVar(me, interp, parm, n, typeInfoPtr)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
int   *typeInfoPtr;
{
  int      argc;
  char     **argv;


  *typeInfoPtr = WW_COLOR;
  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "printfColorRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "printfColorRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return argc;
  }
  free(argv);
  return argc;
}


int
printfPointRIBVar(me, interp, parm, n, typeInfoPtr)
WWEveParser *me;
Tcl_Interp *interp;
char  *parm;
int   n;   
int   *typeInfoPtr;
{
  int      argc;
  char     **argv;


  *typeInfoPtr = WW_POINT;
  if (Tcl_SplitList(interp, parm, &argc, &argv) != TCL_OK)
  {  strcpy(errBuf, "printfPointRIBVar : problem splitting list");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  if (argc % (n*3))
  {  sprintf(errBuf, "printfPointRIBVar : expected parameter to be in groups of %d", n);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     free(argv);
     return argc;
  }
  free(argv);
  return argc;
}


int
declareBMRTSpecificStuff(me, interp)
WWEveParser    *me;
Tcl_Interp     *interp;
{
  RIB_var_t    *aRIBVar;


  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var include"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("include")), "include");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("include", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var shadows"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("shadows")), "shadows");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("shadows", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var verbosity"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("verbosity")), "verbosity");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("verbosity", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var casts_shadows"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("casts_shadows")), "casts_shadows");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("casts_shadows", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var zonal"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("zonal")), "zonal");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("zonal", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var patchsize"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("patchsize")), "patchsize");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("patchsize", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var minshadowbias"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("minshadowbias")), "minshadowbias");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("minshadowbias", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var minsize"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("minsize")), "minsize");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("minsize", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var elemsize"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("elemsize")), "elemsize");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("elemsize", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var displacement"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("displacement")), "displacement");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("displacement", "uniform float");
  list_put(me->rib_var_list, aRIBVar);



  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var patch_maxlevel"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("patch_maxlevel")), "patch_maxlevel");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("patch_maxlevel", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var max_raylevel"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("max_raylevel")), "max_raylevel");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("max_raylevel", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var minsamples"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("minsamples")), "minsamples");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("minsamples", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var maxsamples"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("maxsamples")), "maxsamples");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("maxsamples", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var branch_ratio"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("branch_ratio")), "branch_ratio");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("branch_ratio", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var max_branch_ratio"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("max_branch_ratio")), "max_branch_ratio");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("max_branch_ratio", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var binary"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("binary")), "binary");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("binary", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var averagecolor"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("averagecolor")), "averagecolor");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("color")), "color");
  aRIBVar->encodeFunc = encodeColorRIBVar;
  aRIBVar->archiveFunc = archiveColorRIBVar;
  aRIBVar->printfFunc = printfColorRIBVar;
  aRIBVar->token = RiDeclare("averagecolor", "uniform color");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareBMRTSpecificStuff :  unable to malloc memory for RIB var emissioncolor"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("emissioncolor")), "emissioncolor");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("color")), "color");
  aRIBVar->encodeFunc = encodeColorRIBVar;
  aRIBVar->archiveFunc = archiveColorRIBVar;
  aRIBVar->printfFunc = printfColorRIBVar;
  aRIBVar->token = RiDeclare("emissioncolor", "uniform color");
  list_put(me->rib_var_list, aRIBVar);

  return 1;
}


int
declareGESTELSpecificStuff(me, interp)
WWEveParser    *me;
Tcl_Interp     *interp;
{
  RIB_var_t    *aRIBVar;


  /* add in the few known string ones */
  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareGESTELSpecificStuff :  unable to malloc memory for RIB var name"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("shader")), "shader");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("shader", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declareGESTELSpecificStuff :  unable to malloc memory for RIB var name"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("texture")), "texture");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("texture", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  return 1;
}


int
declarePIXARSpecificStuff(me, interp)
WWEveParser    *me;
Tcl_Interp     *interp;
{
  RIB_var_t    *aRIBVar;


  /* add in the few known string ones */
  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var name"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("name")), "name");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("name", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var format"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("format")), "format");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("format", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var shadinggroup"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("shadinggroup")), "shadinggroup");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("shadinggroup", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var texturename"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("texturename")), "texturename");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("texturename", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var lightcolor"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("lightcolor")), "lightcolor");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("color")), "color");
  aRIBVar->encodeFunc = encodeColorRIBVar;
  aRIBVar->archiveFunc = archiveColorRIBVar;
  aRIBVar->printfFunc = printfColorRIBVar;
  aRIBVar->token = RiDeclare("lightcolor", "uniform color");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var zthreshold"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("zthreshold")), "zthreshold");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("color")), "color");
  aRIBVar->encodeFunc = encodeColorRIBVar;
  aRIBVar->archiveFunc = archiveColorRIBVar;
  aRIBVar->printfFunc = printfColorRIBVar;
  aRIBVar->token = RiDeclare("zthreshold", "uniform color");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var Ng"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("Ng")), "Ng");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("point")), "point");
  aRIBVar->encodeFunc = encodePointRIBVar;
  aRIBVar->archiveFunc = archivePointRIBVar;
  aRIBVar->printfFunc = printfPointRIBVar;
  aRIBVar->token = RiDeclare("Ng", "uniform point");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var to"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("to")), "to");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("point")), "point");
  aRIBVar->encodeFunc = encodePointRIBVar;
  aRIBVar->archiveFunc = archivePointRIBVar;
  aRIBVar->printfFunc = printfPointRIBVar;
  aRIBVar->token = RiDeclare("to", "uniform point");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var from"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("from")), "from");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("point")), "point");
  aRIBVar->encodeFunc = encodePointRIBVar;
  aRIBVar->archiveFunc = archivePointRIBVar;
  aRIBVar->printfFunc = printfPointRIBVar;
  aRIBVar->token = RiDeclare("from", "uniform point");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var binary"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("binary")), "binary");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("binary", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var gridsize"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("gridsize")), "gridsize");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("gridsize", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var eyesplits"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("eyesplits")), "eyesplits");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("eyesplits", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var bucketsize"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("bucketsize")), "bucketsize");
  aRIBVar->n = 2;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("bucketsize", "uniform integer[2]");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var endofframe"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("endofframe")), "endofframe");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("endofframe", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var dynamic"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("dynamic")), "dynamic");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("dynamic", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var texturememory"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("texturememory")), "texturememory");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("texturememory", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var subwindow"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("subwindow")), "subwindow");
  aRIBVar->n = 5;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("subwindow", "uniform integer[5]");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var bucketstride"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("bucketstride")), "bucketstride");
  aRIBVar->n = 2;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("bucketstride", "uniform integer[2]");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var merge"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("merge")), "merge");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("merge", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var jitter"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("jitter")), "jitter");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("integer")), "integer");
  aRIBVar->encodeFunc = encodeIntegerRIBVar;
  aRIBVar->archiveFunc = archiveIntegerRIBVar;
  aRIBVar->printfFunc = printfIntegerRIBVar;
  aRIBVar->token = RiDeclare("jitter", "uniform integer");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var intensity"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("intensity")), "intensity");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("intensity", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var displacement"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("displacement")), "displacement");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("displacement", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var extremedisplacement"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("extremedisplacement")), "extremedisplacement");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("extremedisplacement", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var gridarea"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("gridarea")), "gridarea");
  aRIBVar->n = 2;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("gridarea", "uniform float[2]");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var nearhither"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("nearhither")), "nearhither");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("nearhither", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var epsilon1"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("epsilon1")), "epsilon1");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("epsilon1", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var epsilon2"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("epsilon2")), "epsilon2");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("epsilon2", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var bias0"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("bias0")), "bias0");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("bias0", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var bias1"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("bias1")), "bias1");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("float")), "float");
  aRIBVar->encodeFunc = encodeFloatRIBVar;
  aRIBVar->archiveFunc = archiveFloatRIBVar;
  aRIBVar->printfFunc = printfFloatRIBVar;
  aRIBVar->token = RiDeclare("bias1", "uniform float");
  list_put(me->rib_var_list, aRIBVar);

  aRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!aRIBVar)
  {  sprintf(errBuf, "declarePIXARSpecificStuff :  unable to malloc memory for RIB var vfxinstance"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  aRIBVar->name = strcpy((char *)malloc(1 + strlen("vfxinstance")), "vfxinstance");
  aRIBVar->n = 1;
  aRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
  aRIBVar->type = strcpy((char *)malloc(1 + strlen("string")), "string");
  aRIBVar->encodeFunc = encodeStringRIBVar;
  aRIBVar->archiveFunc = archiveStringRIBVar;
  aRIBVar->printfFunc = printfStringRIBVar;
  aRIBVar->token = RiDeclare("texturename", "uniform string");
  list_put(me->rib_var_list, aRIBVar);

  return 1;
}


RIB_var_t
*getRIBVarGivenName(me, name)
WWEveParser  *me;
char          *name;
{
  int        i, howMany = list_size(me->rib_var_list);
  RIB_var_t  *aRIBVar;


  /* is it a user defined token? */
  for (i = 0; i < howMany; i++)
  {  aRIBVar = (RIB_var_t *)list_get_nth(me->rib_var_list, i);
     if (!strcmp(aRIBVar->name, name))
     {  return (aRIBVar);
     }
  }
  return (RIB_var_t *)NULL;
}


/* NOTE: need a way to map declares and types to user defined tokens.
         Shouldn't be too hard...  we should just have some static 
         pointer to a dynamic table.  The table should get initialized 
         when RiBegin() is called.  It needs to contain 5 lists: the 
	 names of the tokens which correspond to each of the RenderMan 
	 types that can be declared using 
	 RiDeclare() (point|color|float|integer|string).
 */

/* need to make these macros give up immediately if (!x) */
/* wave! need to add the new tokens I've added in additions to the declareXXXStuff() routines */

#define isColorToken(x, n) ((n) && (   ((x == RI_CS)) || ((x == RI_OS)) \
                                    || ((x == RI_LIGHTCOLOR)) || ((x == RI_SPECULARCOLOR)) || ((x == RI_BACKGROUND)) \
                                    || ((x == RI_RGB)) || ((!strcmp(n, "zthreshold")))))

#define isPointToken(x, n) ((n) && (   ((x == RI_P)) || ((x == RI_N)) \
                                    || ((x == RI_NP)) || ((!strcmp(n, "Ng"))) || ((x == RI_FROM)) \
                                    || ((x == RI_TO))))

#define isIntegerToken(x, n) ((n) && (   ((!strcmp(n, "binary"))) || ((!strcmp(n, "gridsize"))) || ((!strcmp(n, "eyesplits"))) \
                                      || ((!strcmp(n, "bucketsize"))) || ((!strcmp(n, "endofframe"))) \
                                      || ((!strcmp(n, "dynamic"))) || ((!strcmp(n, "texturememory"))) || ((!strcmp(n, "subwindow"))) \
                                      || ((!strcmp(n, "bucketstride"))) || ((!strcmp(n, "merge"))) || ((x == RI_ORIGIN)) \
                                      || ((!strcmp(n, "jitter")))))

// took out trim deviation...
#define isFloatToken(x, n) ((n) && (   ((x == RI_PZ)) || ((x == RI_PW)) || ((x == RI_S)) \
                                    || ((x == RI_T)) || ((x == RI_A)) || ((x == RI_AZ)) \
                                    || ((x == RI_RGBAZ)) || ((x == RI_RGBZ)) || ((x == RI_FLATNESS)) \
                                    || ((x == RI_FOV)) || ((x == RI_INTENSITY)) \
                                    || ((x == RI_CONEANGLE)) || ((x == RI_CONEDELTAANGLE)) || ((x == RI_BEAMDISTRIBUTION)) \
                                    || ((x == RI_KA)) || ((x == RI_KD)) || ((x == RI_KS)) \
                                    || ((x == RI_ROUGHNESS)) || ((x == RI_KR)) || ((x == RI_MINDISTANCE)) \
                                    || ((x == RI_MAXDISTANCE)) || ((x == RI_DISTANCE)) || ((x == RI_AMPLITUDE)) \
                                    || ((x == RI_RGBA)) || ((x == RI_ST)) || ((x == RI_Z)) || ((!strcmp(n, "extremedisplacement"))) \
                                    || ((!strcmp(n, "displacement"))) || ((!strcmp(n, "gridarea"))) || ((!strcmp(n, "nearhither"))) \
                                    || ((!strcmp(n, "epsilon1"))) || ((!strcmp(n, "epsilon2"))) || ((!strcmp(n, "bias0"))) \
                                    || ((!strcmp(n, "bias1")))))

RtPointer
parseTokenNameAndParameterIntoParm(me, interp, theToken, tokenName, parmAsString, errPtr)
WWEveParser  *me;
Tcl_Interp    *interp;
RtToken       theToken;
char          *tokenName, *parmAsString;
int           *errPtr;
{
  int        argc, i;
  char       **argv;
  RIB_var_t  *theRIBVar;


  /* first we see if the parmAsString is NULL.  If so, return success and RI_NULL */
  if (!parmAsString)
  {  *errPtr = 0;
     return RI_NULL;
  }

  /* next we see if the token is one of the built-in RenderMan-defined ones */
  /* if it is, we, deal with it and return. */
  /* if not, we have to grab the RIB_var_t structure and use that to build up parm appropriately */

  if (isColorToken(theToken, tokenName))
  {  RtColor  *colors, *colorPtr;

     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as color token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoParm() : colors specified with %s must be given in 3-vectors : there were %d elements in the list", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        return RI_NULL;
     }
     colors = (RtColor *)malloc((argc/3) * sizeof(RtColor));
     colorPtr = colors;
     for (i = 0; i < argc; i += 3)
     {  (*colorPtr)[0] = (RtFloat)atof(argv[i+0]);
        (*colorPtr)[1] = (RtFloat)atof(argv[i+1]);
        (*colorPtr)[2] = (RtFloat)atof(argv[i+2]);
	colorPtr++;
     }
     free(argv);
     *errPtr = 0;
     return (RtPointer)(colors);
  }

  if (isPointToken(theToken, tokenName))
  {  RtPoint  *points, *pointPtr;
    
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as point token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoParm() : points specified with %s must be given in 3-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        return RI_NULL;
     }
     points = (RtPoint *)malloc((argc/3) * sizeof(RtPoint));
     pointPtr = points;
     for (i = 0; i < argc; i += 3)
     {  (*pointPtr)[0] = (RtFloat)atof(argv[i+0]);
        (*pointPtr)[1] = (RtFloat)atof(argv[i+1]);
        (*pointPtr)[2] = (RtFloat)atof(argv[i+2]);
	pointPtr++;
     }
     free(argv);
     *errPtr = 0;
     return (RtPointer)points;
  }

  if (isFloatToken(theToken, tokenName))
  {  RtFloat  *floats, *floatPtr;

     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as float token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }

     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((theToken == RI_AZ) && (argc % 2))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return (RtPointer)0;
     }
     if ((theToken == RI_PW) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBAZ) && (argc % 5))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBZ) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBA) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "gridarea")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }

     floats = (RtFloat *)malloc((argc * sizeof(RtFloat)));
     floatPtr = floats;
     for (i = 0; i < argc; i++)
     {  *floatPtr++ = (RtFloat)atof(argv[i]);
     }
     free(argv);
     *errPtr = 0;
     return (RtPointer)floats;
  }

  if (isIntegerToken(theToken, tokenName))
  {  RtInt  *integers, *integerPtr;


     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as integer token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }

     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((!strcmp(tokenName, "bucketsize")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "subwindow")) && (argc % 5))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "bucketstride")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ORIGIN) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoParm() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }

     integers = (RtInt *)malloc((argc * sizeof(RtInt)));
     integerPtr = integers;
     for (i = 0; i < argc; i++)
     {  *integerPtr++ = (RtInt)atoi(argv[i]);
     }
     free(argv);
     *errPtr = 0;
     return (RtPointer)integers;
  }

  theRIBVar = getRIBVarGivenName(me, tokenName);
  if (theRIBVar) /* must be a user defined RIB variable */
  {  RtPointer  retPtr = RI_NULL;

     retPtr = (RtPointer)(theRIBVar->encodeFunc(me, interp, parmAsString, theRIBVar->n));
     *errPtr = 0;
     if (!retPtr)
     {  *errPtr = 1;
     }
     return retPtr;
  }

  *errPtr = 1;
  sprintf(errBuf, 
	  "parseTokenNameAndParameterIntoParm() : the token <%s> was never formally declared with RiDeclare() - how the hell am I supposed to know what type it is?", 
	  tokenName);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);
  return (RtPointer)RI_NULL;
}


char 
*parseTokenNameAndParameterIntoArchiveInfo(me, interp, theToken, tokenName, parmAsString, errPtr)
WWEveParser  *me;
Tcl_Interp    *interp;
RtToken       theToken;
char          *tokenName, *parmAsString;
int           *errPtr;
{
  int        argc;
  char       **argv;
  RIB_var_t  *theRIBVar;
  char       archiveInfo[256];


  /* first we see if the parmAsString is NULL.  If so, return success and RI_NULL */
  if (!parmAsString)
  {  *errPtr = 0;
     return NXCopyStringBuffer("");
  }

  /* next we see if the token is one of the built-in RenderMan-defined ones */
  /* if it is, we, deal with it and return. */
  /* if not, we have to grab the RIB_var_t structure and use that to build up parm appropriately */

  if (isColorToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as color token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoArchiveInfo() : colors specified with %s must be given in 3-vectors : there were %d elements in the list", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        return RI_NULL;
     }
     *errPtr = 0;
     free(argv);
     sprintf(archiveInfo, "[%df]", argc);
     return NXCopyStringBuffer(archiveInfo);
  }

  if (isPointToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as point token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoArchiveInfo() : points specified with %s must be given in 3-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        return RI_NULL;
     }
     free(argv);
     *errPtr = 0;
     sprintf(archiveInfo, "[%df]", argc);
     return NXCopyStringBuffer(archiveInfo);
  }

  if (isFloatToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as float token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((theToken == RI_AZ) && (argc % 2))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return (RtPointer)0;
     }
     if ((theToken == RI_PW) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBAZ) && (argc % 5))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBZ) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_RGBA) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "gridarea")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }

     free(argv);
     *errPtr = 0;
     sprintf(archiveInfo, "[%df]", argc);
     return NXCopyStringBuffer(archiveInfo);
  }

  if (isIntegerToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoParm() : problem splitting list as integer token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return RI_NULL;
     }
     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((!strcmp(tokenName, "bucketsize")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "subwindow")) && (argc % 5))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((!strcmp(tokenName, "bucketstride")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }
     if ((theToken == RI_ORIGIN) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoArchiveInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
         return RI_NULL;
     }

     free(argv);
     *errPtr = 0;
     sprintf(archiveInfo, "[%di]", argc);
     return NXCopyStringBuffer(archiveInfo);
  }

  theRIBVar = getRIBVarGivenName(me, tokenName);
  if (theRIBVar) /* must be a user defined RIB variable */
  {  char  *retPtr = NULL;

     retPtr = (char *)(theRIBVar->archiveFunc(me, interp, parmAsString, theRIBVar->n));
     *errPtr = 0;
     if (!retPtr)
     {  *errPtr = 1;
     }
     return retPtr;
  }

  *errPtr = 1;
  sprintf(errBuf, 
	  "parseTokenNameAndParameterIntoArchiveInfo() : the token <%s> was never formally declared with RiDeclare() - how the hell am I supposed to know what type it is?", 
	  tokenName);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);
  return (RtPointer)RI_NULL;
}


int
parseTokenNameAndParameterIntoPrintfInfo(me, interp, theToken, tokenName, parmAsString, errPtr, typeInfoPtr, howManyPtr)
WWEveParser  *me;
Tcl_Interp    *interp;
RtToken       theToken;
char          *tokenName, *parmAsString;
int           *errPtr, *typeInfoPtr, *howManyPtr;
{
  int          argc;
  char         **argv;
  RIB_var_t    *theRIBVar;


  /* first we see if the parmAsString is NULL.  If so, return success and RI_NULL */
  if (!parmAsString)
  {  *errPtr = 0;
     *typeInfoPtr = -1;
     *howManyPtr = 0;
     return *howManyPtr;
  }


  /* next we see if the token is one of the built-in RenderMan-defined ones */
  /* if it is, we, deal with it and return. */
  /* if not, we have to grab the RIB_var_t structure and use that to build up parm appropriately */

  if (isColorToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoPrintfInfo() : problem splitting list as color token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return 0;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoPrintfInfo() : colors specified with %s must be given in 3-vectors : there were %d elements in the list", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     *errPtr = 0;
     free(argv);
     *typeInfoPtr = WW_COLOR;
     *howManyPtr = argc;
     return *howManyPtr;
  }

  if (isPointToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoPrintfInfo() : problem splitting list as point token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return 0;
     }
     if (argc % 3)
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoPrintfInfo() : points specified with %s must be given in 3-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);
        *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     free(argv);
     *errPtr = 0;
     *typeInfoPtr = WW_POINT;
     *howManyPtr = argc;
     return *howManyPtr;
  }

  if (isFloatToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoPrintfInfo() : problem splitting list as float token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return 0;
     }
     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((theToken == RI_AZ) && (argc % 2))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  
        *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_PW) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_RGBAZ) && (argc % 5))
     {  sprintf(errBuf, 
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_RGBZ) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_RGBA) && (argc % 4))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 4-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((!strcmp(tokenName, "gridarea")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_ST) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }

     free(argv);
     *errPtr = 0;
     *typeInfoPtr = WW_FLOAT;
     *howManyPtr = argc;
     return *howManyPtr;
  }

  if (isIntegerToken(theToken, tokenName))
  {  
     if (Tcl_SplitList(interp, parmAsString, &argc, &argv) != TCL_OK)
     {  strcpy(errBuf, "parseTokenNameAndParameterIntoPrintfInfo() : problem splitting list as integer token");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return 0;
     }
     /* need to check for various special cases here to do additional argc sanity check */ 
     if ((!strcmp(tokenName, "bucketsize")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((!strcmp(tokenName, "subwindow")) && (argc % 5))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 5-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((!strcmp(tokenName, "bucketstride")) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }
     if ((theToken == RI_ORIGIN) && (argc % 2))
     {  sprintf(errBuf,
		"parseTokenNameAndParameterIntoPrintfInfo() : parameters for %s must be given in 2-vectors - this list had %d elements", 
		tokenName, argc);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        free(argv);  *errPtr = 1;
        *typeInfoPtr = -1;
        *howManyPtr = 0;
        return *howManyPtr;
     }

     free(argv);
     *errPtr = 0;
     *typeInfoPtr = WW_INT;
     *howManyPtr = argc;
     return *howManyPtr;
  }

  theRIBVar = getRIBVarGivenName(me, tokenName);
  if (theRIBVar) /* must be a user defined RIB variable */
  {  *howManyPtr = (int)(theRIBVar->printfFunc(me, interp, parmAsString, theRIBVar->n, typeInfoPtr));
     *errPtr = 0;
     if (!*howManyPtr)
     {  *errPtr = 1;
     } 
     return *howManyPtr;
  }

  *errPtr = 1;
  sprintf(errBuf, 
	  "parseTokenNameAndParameterIntoPrintfInfo() : the token <%s> was never formally declared with RiDeclare() - how the hell am I supposed to know what type it is?", 
	  tokenName);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);
  return 0;
}


RtToken
getTokenGivenName(me, name)
WWEveParser  *me;
char          *name;
{
  int          i, howMany = list_size(me->rib_var_list);
  RIB_var_t  *aRIBVar;


  /* is it built-in? */
#if 0
  if (!strcmp(name, "bezier")) {  return RI_BEZIER;}
  if (!strcmp(name, "b-spline")) {  return RI_BSPLINE;}
  if (!strcmp(name, "catmull-rom")) {  return RI_CATMULLROM;}
  if (!strcmp(name, "hermite")) {  return RI_HERMITE;}
  if (!strcmp(name, "power")) {  return RI_POWER;}
#endif
  if (!strcmp(name, "framebuffer")) {  return RI_FRAMEBUFFER;}
  if (!strcmp(name, "file")) {  return RI_FILE;}
  if (!strcmp(name, "rgb")) {  return RI_RGB;}
  if (!strcmp(name, "rgba")) {  return RI_RGBA;}
  if (!strcmp(name, "rgbz")) {  return RI_RGBZ;}
  if (!strcmp(name, "rgbaz")) {  return RI_RGBAZ;}
  if (!strcmp(name, "a")) {  return RI_A;}
  if (!strcmp(name, "z")) {  return RI_Z;}
  if (!strcmp(name, "az")) {  return RI_AZ;}
  if (!strcmp(name, "perspective")) {  return RI_PERSPECTIVE;}
  if (!strcmp(name, "orthographic")) {  return RI_ORTHOGRAPHIC;}
  if (!strcmp(name, "hidden")) {  return RI_HIDDEN;}
  if (!strcmp(name, "paint")) {  return RI_PAINT;}
  if (!strcmp(name, "constant")) {  return RI_CONSTANT;}
  if (!strcmp(name, "smooth")) {  return RI_SMOOTH;}
  if (!strcmp(name, "origin")) {  return RI_ORIGIN;}
  if (!strcmp(name, "flatness")) {  return RI_FLATNESS;}
  //if (!strcmp(name, "trimdeviation")) {  return RI_TRIMDEVIATION;}
  if (!strcmp(name, "fov")) {  return RI_FOV;}
  if (!strcmp(name, "ambientlight")) {  return RI_AMBIENTLIGHT;}
  if (!strcmp(name, "pointlight")) {  return RI_POINTLIGHT;}
  if (!strcmp(name, "distantlight")) {  return RI_DISTANTLIGHT;}
  if (!strcmp(name, "spotlight")) {  return RI_SPOTLIGHT;}
  if (!strcmp(name, "intensity")) {  return RI_INTENSITY;}
  if (!strcmp(name, "lightcolor")) {  return RI_LIGHTCOLOR;}
  if (!strcmp(name, "from")) {  return RI_FROM;}
  if (!strcmp(name, "to")) {  return RI_TO;}
  if (!strcmp(name, "coneangle")) {  return RI_CONEANGLE;}
  if (!strcmp(name, "conedeltaangle")) {  return RI_CONEDELTAANGLE;}
  if (!strcmp(name, "beamdistribution")) {  return RI_BEAMDISTRIBUTION;}
  if (!strcmp(name, "matte")) {  return RI_MATTE;}
  if (!strcmp(name, "metal")) {  return RI_METAL;}
  if (!strcmp(name, "shinymetal")) {  return RI_SHINYMETAL;}
  if (!strcmp(name, "plastic")) {  return RI_PLASTIC;}
  if (!strcmp(name, "paintedplastic")) {  return RI_PAINTEDPLASTIC;}
  if (!strcmp(name, "Ka")) {  return RI_KA;}
  if (!strcmp(name, "Kd")) {  return RI_KD;}
  if (!strcmp(name, "Ks")) {  return RI_KS;}
  if (!strcmp(name, "roughness")) {  return RI_ROUGHNESS;}
  if (!strcmp(name, "specularcolor")) {  return RI_SPECULARCOLOR;}
  if (!strcmp(name, "Kr")) {  return RI_KR;}
  if (!strcmp(name, "depthcue")) {  return RI_DEPTHCUE;}
  if (!strcmp(name, "fog")) {  return RI_FOG;}
  if (!strcmp(name, "bumpy")) {  return RI_BUMPY;}
  if (!strcmp(name, "mindistance")) {  return RI_MINDISTANCE;}
  if (!strcmp(name, "maxdistance")) {  return RI_MAXDISTANCE;}
  if (!strcmp(name, "background")) {  return RI_BACKGROUND;}
  if (!strcmp(name, "distance")) {  return RI_DISTANCE;}
  if (!strcmp(name, "amplitude")) {  return RI_AMPLITUDE;}
  if (!strcmp(name, "raster")) {  return RI_RASTER;}
  if (!strcmp(name, "screen")) {  return RI_SCREEN;}
  if (!strcmp(name, "camera")) {  return RI_CAMERA;}
  if (!strcmp(name, "world")) {  return RI_WORLD;}
  if (!strcmp(name, "object")) {  return RI_OBJECT;}
  if (!strcmp(name, "inside")) {  return RI_INSIDE;}
  if (!strcmp(name, "outside")) {  return RI_OUTSIDE;}
  if (!strcmp(name, "lh")) {  return RI_LH;}
  if (!strcmp(name, "rh")) {  return RI_RH;}
  if (!strcmp(name, "P")) {  return RI_P;}
  if (!strcmp(name, "Pz")) {  return RI_PZ;}
  if (!strcmp(name, "Pw")) {  return RI_PW;}
  if (!strcmp(name, "N")) {  return RI_N;}
  if (!strcmp(name, "Np")) {  return RI_NP;}
  if (!strcmp(name, "Cs")) {  return RI_CS;}
  if (!strcmp(name, "Os")) {  return RI_OS;}
  if (!strcmp(name, "s")) {  return RI_S;}
  if (!strcmp(name, "t")) {  return RI_T;}
  if (!strcmp(name, "st")) {  return RI_ST;}
  if (!strcmp(name, "bilinear")) {  return RI_BILINEAR;}
  if (!strcmp(name, "bicubic")) {  return RI_BICUBIC;}
  if (!strcmp(name, "primitive")) {  return RI_PRIMITIVE;}
  if (!strcmp(name, "intersection")) {  return RI_INTERSECTION;}
  if (!strcmp(name, "union")) {  return RI_UNION;}
  if (!strcmp(name, "difference")) {  return RI_DIFFERENCE;}
  if (!strcmp(name, "periodic")) {  return RI_PERIODIC;}
  if (!strcmp(name, "nonperiodic")) {  return RI_NONPERIODIC;}
  if (!strcmp(name, "clamp")) {  return RI_CLAMP;}
  if (!strcmp(name, "black")) {  return RI_BLACK;}
  if (!strcmp(name, "abort")) {  return RI_ABORT;}
  if (!strcmp(name, "comment")) {  return RI_COMMENT;}
  if (!strcmp(name, "structure")) {  return RI_STRUCTURE;}
  if (!strcmp(name, "identifier")) {  return RI_IDENTIFIER;}

  /* we'll ignore the 4.0 tokens for now */

  /* is it a user defined token? */
  for (i = 0; i < howMany; i++)
  {  aRIBVar = (RIB_var_t *)list_get_nth(me->rib_var_list, i);
     if (!strcmp(aRIBVar->name, name))
     {  return (aRIBVar->token);
     }
  }
  return RI_NULL;
}

int
buildParameterList(me, interp, n, tokens, parms, archiveVector, printfNVector, printfTypeVector, startingArgIndex, argv)
WWEveParser  *me;
Tcl_Interp    *interp;
int           n;
RtToken       **tokens;
RtPointer     **parms;
char          ***archiveVector;
int           **printfNVector;
int           **printfTypeVector;
int           startingArgIndex;
char          **argv;
{
  RtToken    *tokenPtr = (RtToken *)RI_NULL;
  RtPointer  *parmPtr = (RtPointer *)RI_NULL;
  int        err, i, j, *printfNPtr, *printfTypePtr;
  char       *tokenName, **archiveVectorPtr = NULL;


  if (n == 0)
  {  return 1;
  }
  if (n < 0)
  {  sprintf(errBuf, "buildParameterList() : weird number of arguments");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  *tokens = (RtToken *)malloc(n * sizeof(RtToken));
  *parms = (RtPointer *)malloc(n * sizeof(RtPointer));
  *archiveVector = (char **)malloc(n * sizeof(char *));
  *printfNVector = (int *)malloc(n * sizeof(int));
  *printfTypeVector = (int *)malloc(n * sizeof(int));
  if ((!(*tokens)) || (!(*parms)) || (!(*archiveVector)) || (!(*printfNVector)) || (!(*printfTypeVector)))
  {  if (*tokens) { free(*tokens); }
     if (*parms) { free(*parms); }
     if (*archiveVector) { free(*archiveVector); }
     if (*printfNVector) { free(*printfNVector); }
     if (*printfTypeVector) { free(*printfTypeVector); }
     sprintf(errBuf, "buildParameterList() : unable to malloc enough memory for parameter list!");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }
  tokenPtr = *tokens; parmPtr = *parms; archiveVectorPtr = *archiveVector; printfNPtr = *printfNVector; printfTypePtr = *printfTypeVector;
  err = 0;

  for (i = startingArgIndex; i < ((n*2) + startingArgIndex); i += 2)
  {  tokenName = (char *)strcpy(malloc(1 + strlen(argv[i])), argv[i]);
     *tokenPtr = getTokenGivenName(me, tokenName);
     *parmPtr = parseTokenNameAndParameterIntoParm(me, interp, *tokenPtr, tokenName, argv[i + 1], &err);
     if (err)
     {  /* we assume something bad happened in parsing the parameter */
	/* we also assume that errBuf has been set appropriately */
	/* clean up and get out - really should go back over both lists... */
	/* i.e. unwind over i back to 2, freeing both token and parm and their contents */
        /* actually, it's only if I malloc'ed the tokenPtr, which, in most cases I won't have */
        /* for now, the bookkeeping is too much of a pain... FIX */
        j = i;
	while (j >= startingArgIndex)
	{ if (*parmPtr) 
          { free(*parmPtr); 
          }
	  tokenPtr--; 
          parmPtr--; 
          j -= 2;
        }
        return 0;
    } 
    *archiveVectorPtr = parseTokenNameAndParameterIntoArchiveInfo(me, interp, *tokenPtr, tokenName, argv[i + 1], &err);
     if (err)
     {  /* we assume something bad happened in parsing the parameter */
	/* we also assume that errBuf has been set appropriately */
	/* clean up and get out - really should go back over both lists... */
	/* i.e. unwind over i back to 2, freeing both token and parm and their contents */
        /* actually, it's only if I malloc'ed the tokenPtr, which, in most cases I won't have */
        /* for now, the bookkeeping is too much of a pain... FIX */
        j = i;
	while (j >= startingArgIndex)
	{ if (*parmPtr) 
          { free(*parmPtr); 
          }
	  tokenPtr--; 
          parmPtr--; 
          j -= 2;
        }
        return 0;
    } 
    *printfNPtr = parseTokenNameAndParameterIntoPrintfInfo(me, interp, *tokenPtr, tokenName, argv[i + 1], &err, printfTypePtr, printfNPtr);
     if (err)
     {  /* we assume something bad happened in parsing the parameter */
	/* we also assume that errBuf has been set appropriately */
	/* clean up and get out - really should go back over both lists... */
	/* i.e. unwind over i back to 2, freeing both token and parm and their contents */
        /* actually, it's only if I malloc'ed the tokenPtr, which, in most cases I won't have */
        /* for now, the bookkeeping is too much of a pain... FIX */
        j = i;
	while (j >= startingArgIndex)
	{ if (*parmPtr) 
          { free(*parmPtr); 
          }
	  tokenPtr--; 
          parmPtr--; 
          j -= 2;
        }
        return 0;
    } 
    tokenPtr++; parmPtr++; archiveVectorPtr++; printfNPtr++; printfTypePtr++;
  }
  return 1;
}


static int
cmd_massageRIB(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "inputRIBFile outputEveFile";
  int	       num_args = 3;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (!massageRIB(interp, argv[1], argv[2]))
  {  return TCL_ERROR;
  }

  return TCL_OK;
}


static int
cmd_render(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "inputRIBFile tmpFilename", *tmpFilename, *extension, *extension2, *retBuf;
  int	       num_args = 3, ret,  howMany = list_size(me->rib_var_list), i;
  static char  cmdBuf[2048];
  //BOOL         oldFlag = [[me tclInterp] showErrors];


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  tmpFilename = argv[2];

  extension = argv[1] + (strlen(argv[1]) - 4);
  if ((strlen(argv[1]) > 5) && (!strcmp(extension, ".eve")))
  {  // no need to massage it - it's already in eve format...
     tmpFilename = argv[1];
  }
  else  // check if it's a wwScene file...
  {  extension2 = argv[1] + (strlen(argv[1]) - 8);
     if ((strlen(argv[1]) > 9) && (!strcmp(extension2, ".wwScene")))
     {  // no need to massage it - it's already in eve format...
        tmpFilename = argv[1];
     }
     else
     {  if (!massageRIB(interp, argv[1], tmpFilename))
        {  return TCL_ERROR;
        }
     }
  }
  if ([me riBegun])
  {  // RiClose();
  }

  howMany = list_size(me->rib_parm_list);
  for (i = 0; i < howMany; i++)
  {  list_delete_nth(me->rib_parm_list, 0);
  }

  howMany = list_size(me->rib_var_list);
  for (i = 0; i < howMany; i++)
  {  list_delete_nth(me->rib_var_list, 0);
  }

  howMany = list_size(me->rib_object_list);
  for (i = 0; i < howMany; i++)
  {  list_delete_nth(me->rib_object_list, 0);
  }

  howMany = list_size(me->rib_light_list);
  for (i = 0; i < howMany; i++)
  {  list_delete_nth(me->rib_light_list, 0);
  }

  // RiBegin(argv[2]);
  [me setRiBegun:YES];

  if (!declarePIXARSpecificStuff(me, interp))
  {  return TCL_ERROR;
  }

  if (!declareGESTELSpecificStuff(me, interp))
  {  return TCL_ERROR;
  }

  if (!declareBMRTSpecificStuff(me, interp))
  {  return TCL_ERROR;
  }

  sprintf(cmdBuf, "source {%s}", tmpFilename);
  //[[me tclInterp] setShowErrors:NO];
  retBuf = [[me tclInterp] eval:cmdBuf :&ret];
  if (ret != TCL_OK)
  {  //[me showError:retBuf];
  }
  //[[me tclInterp] setShowErrors:oldFlag];

  if (retBuf) { free(retBuf); }

  // RiEnd();
  [me setRiBegun:NO];

  return ret;
}


static int
cmd_RiDeclare(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name {[uniform|varying|vertex] point|color|float|integer|int|string [{n}]}";
  char       declaration[256], **argv2, **argv3;
  RtToken    returnToken;
  RIB_var_t  *newRIBVar;
  int        argc2, argc3;
  char       *class = NULL, *type = NULL, n = 1;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != 3)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s :problem splitting 3rd arg as list", argv[0]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc > 3) || (argc < 2))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 == 2) /* uniform|varying|vertex point|color|float|integer|int|string [{n}] */
  {  if (   strcmp(argv2[0], "uniform") && strcmp(argv2[0], "varying") && strcmp(argv2[0], "vertex")
         && strcmp(argv2[0], "float") 
            && strcmp(argv2[0], "integer") 
            && strcmp(argv2[0], "int") 
            && strcmp(argv2[0], "string") 
            && strcmp(argv2[0], "point") 
            && strcmp(argv2[0], "color"))
     {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
  }
  if (argc2 == 3) /* uniform|varying|vertex point|color|float|integer|int|string [{n}] */
  {  if (strcmp(argv2[0], "uniform") && strcmp(argv2[0], "varying") && strcmp(argv2[0], "vertex"))
     {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
  }
  if (argc2 == 1) /* point|color|float|integer|int|string */
  {  if (strcmp(argv2[0], "float") && strcmp(argv2[0], "integer") && strcmp(argv2[0], "int") && strcmp(argv2[0], "string") && strcmp(argv2[0], "point") && strcmp(argv2[0], "color"))
     {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     type = argv2[0];
     sprintf(declaration, "%s", type); /* Declare foo float */
  }
  else  /* uniform|varying|vertex point|color|float|integer|int|string [{n}] */
  {  if (argc2 == 2)
     {  if (   strcmp(argv2[0], "uniform") 
            && strcmp(argv2[0], "varying") 
            && strcmp(argv2[0], "vertex")) 
        {  // okay, we're defaulting to "uniform"
           class = "uniform";
           if (   strcmp(argv2[0], "float") 
               && strcmp(argv2[0], "integer") 
               && strcmp(argv2[0], "int") 
               && strcmp(argv2[0], "string") 
               && strcmp(argv2[0], "point") 
               && strcmp(argv2[0], "color"))
           {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
              Tcl_AppendResult(interp, errBuf, (char *)NULL);
              return TCL_ERROR;
           }
           type = argv2[0];
           if (Tcl_SplitList(interp, argv2[1], &argc3, &argv3) != TCL_OK)
           {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv2[1]);
   	      Tcl_AppendResult(interp, errBuf, (char *)NULL);
	      return TCL_ERROR;
           }
           if (argc3 != 1)
           {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
   	      Tcl_AppendResult(interp, errBuf, (char *)NULL);
	      return TCL_ERROR;
           }
           n = atoi(argv3[0]);
           sprintf(declaration, "%s %s[%d]", class, type, n);  /* Declare foo varying float[3] */
        }
        else
        {  if (   strcmp(argv2[1], "float") 
               && strcmp(argv2[1], "integer") 
               && strcmp(argv2[1], "int") 
               && strcmp(argv2[1], "string") 
               && strcmp(argv2[1], "point") 
               && strcmp(argv2[1], "color"))
           {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
              Tcl_AppendResult(interp, errBuf, (char *)NULL);
              return TCL_ERROR;
           }
           class = argv2[0];
           type = argv2[1];
        }
        sprintf(declaration, "%s %s", class, type);  /* Declare foo varying float */
     }
     else /* uniform|varying|vertex point|color|float|integer|int|string {n} */
     {  if (Tcl_SplitList(interp, argv2[2], &argc3, &argv3) != TCL_OK)
        {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv2[2]);
   	   Tcl_AppendResult(interp, errBuf, (char *)NULL);
	   return TCL_ERROR;
        }

        if (argc3 != 1)
        {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
   	   Tcl_AppendResult(interp, errBuf, (char *)NULL);
	   return TCL_ERROR;
        }
        class = argv2[0];
        type = argv2[1];
        n = atoi(argv3[0]);
        sprintf(declaration, "%s %s[%d]", class, type, n);  /* Declare foo varying float[3] */
     }
  }

  returnToken = RiDeclare(argv[1], declaration);

  /* malloc up a RIB_var_t here, stick argv[1] and the token in there.  */
  /* when they hand you back a token (really, the name) look it up */
  newRIBVar = (RIB_var_t *)malloc(sizeof(RIB_var_t));
  if (!newRIBVar)
  {  sprintf(errBuf, "RiDeclare : unable to malloc memory for new RIB var"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBVar->name = strcpy((char *)malloc(1 + strlen(argv[1])), argv[1]);
  newRIBVar->n = n;
  if (argc2 == 1)
  {  newRIBVar->class = strcpy((char *)malloc(1 + strlen("uniform")), "uniform");
     newRIBVar->type = strcpy((char *)malloc(1 + strlen(type)), type);
  }
  else
  {  newRIBVar->class = strcpy((char *)malloc(1 + strlen(class)), class);
     newRIBVar->type = strcpy((char *)malloc(1 + strlen(type)), type);
  }
  newRIBVar->token = returnToken;

  if (!strcmp(newRIBVar->type, "float"))
  {  newRIBVar->encodeFunc = encodeFloatRIBVar;
     newRIBVar->archiveFunc = archiveFloatRIBVar;
     newRIBVar->printfFunc = printfFloatRIBVar;
  }
  if (!strcmp(newRIBVar->type, "integer"))
  {  newRIBVar->encodeFunc = encodeIntegerRIBVar;
     newRIBVar->archiveFunc = archiveIntegerRIBVar;
     newRIBVar->printfFunc = printfIntegerRIBVar;
  }
  if (!strcmp(newRIBVar->type, "string"))
  {  newRIBVar->encodeFunc = encodeStringRIBVar;
     newRIBVar->archiveFunc = archiveStringRIBVar;
     newRIBVar->printfFunc = printfStringRIBVar;
  }
  if (!strcmp(newRIBVar->type, "point"))
  {  newRIBVar->encodeFunc = encodePointRIBVar;
     newRIBVar->archiveFunc = archivePointRIBVar;
     newRIBVar->printfFunc = printfPointRIBVar;
  }
  if (!strcmp(newRIBVar->type, "color"))
  {  newRIBVar->encodeFunc = encodeColorRIBVar;
     newRIBVar->archiveFunc = archiveColorRIBVar;
     newRIBVar->printfFunc = printfColorRIBVar;
  }

  list_put(me->rib_var_list, newRIBVar);

  newRIBCommand = [[RIBDeclare alloc] init];
  [newRIBCommand setName:argv[1] declaration:declaration];
  [newRIBCommand setMyShape:[me currentShape]];

  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  sprintf(interp->result, "%s", newRIBVar->name);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);

  return TCL_OK;
}


static int
cmd_RiBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "name";
  int	       num_args = 2, howMany = list_size(me->rib_var_list), i;
  RtToken      name = RI_NULL;
  RIB_var_t    *aRIBVar;
  RIB_light_t  *aRIBLight;
  RIB_object_t *aRIBObject;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me riBegun])
  {  //RiClose();
  }

  if (argc > 1)
  {  name = (RtToken)argv[1];
  }

  /* clear out the rib_var list */
  for (i = 0; i < howMany; i++)
  {  aRIBVar = (RIB_var_t *)list_get_nth(me->rib_var_list, 0);
     list_delete_nth(me->rib_var_list, 0);
     if (aRIBVar)
     {  free(aRIBVar);
     }
  }

  /* don't free the parm list - each RIBCommand will do that */

  /* free object list */
  howMany = list_size(me->rib_object_list);
  for (i = 0; i < howMany; i++)
  {  aRIBObject = (RIB_object_t *)(list_get_nth(me->rib_object_list, 0));
     list_delete_nth(me->rib_object_list, 0);
     if (aRIBObject)
     {  free(aRIBObject);
     }
  }

  /* free light list */
  howMany = list_size(me->rib_light_list);
  for (i = 0; i < howMany; i++)
  {  aRIBLight = (RIB_light_t *)(list_get_nth(me->rib_light_list, 0));
     list_delete_nth(me->rib_light_list, 0);
     if (aRIBLight)
     {  free(aRIBLight);
     }
  }

  // RiBegin(name);
  [me setRiBegun:YES];

  if (!declarePIXARSpecificStuff(me, interp))
  {  return TCL_ERROR;
  }

  if (!declareGESTELSpecificStuff(me, interp))
  {  return TCL_ERROR;
  }

  return TCL_OK;
}


static int
cmd_RiEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char       *my_args = "";
  int	     num_args = 1, howMany, i;
  RtPointer  aPtr;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiEnd();

  [me setRiBegun:NO];

  /* free parm list */
  howMany = list_size(me->rib_parm_list);
  for (i = 0; i < howMany; i++)
  {  aPtr = (RtPointer)list_get_nth(me->rib_parm_list, 0);
     list_delete_nth(me->rib_parm_list, 0);
     if (aPtr)
     {  free(aPtr);
     }
  }

  return TCL_OK;
}


static int
cmd_RiWorldBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newShape;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  newShape = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]];
  [newShape setShapeName:"World"];
  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];


  return TCL_OK;
}


static int
cmd_RiWorldEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiWorldEnd();
  // at this point, calculate bounding box of current shape
  //[[me currentShape] logTransformWithMsg:"WorldEnd before boundingBox calc"];
  [[me currentShape] calculateBoundingBoxStartingAt:[[me sceneClock] timestamp] endingAt:[[me sceneClock] timestamp]]; 
  //[[me currentShape] logTransformWithMsg:"WorldEnd after boundingBox calc"];
  [me setRiBegun:NO];

  return TCL_OK;
}


static int
cmd_RiColorSamples(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "{nRGB} ... {RGBn}";
  int	   num_args = 3, vecLen, i, argc2;
  RtInt    n, n1, n2;
  char     **argv2;
  RtFloat  *nRGB, *RGBn;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s: problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  n1 = argc2; 
  if (n1 % 3)
  {  sprintf(errBuf, "%s must be a %d x 3 transform : USAGE: %s %s", argv[1], (int)(n1/3), argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = n1/3;
  vecLen = n1;
  nRGB = (RtFloat *)malloc(vecLen * sizeof(RtFloat));
  for (i = 0; i < vecLen; i++)
  {  nRGB[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n2 = argc2; 
  if ((n2 % 3) || (n1 != n2))
  {  sprintf(errBuf, "%s must be a %d x 3 transform : USAGE: %s %s", argv[2], (int)(n2/3), argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  RGBn = (RtFloat *)malloc(vecLen * sizeof(RtFloat));
  for (i = 0; i < vecLen; i++)
  {  RGBn[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  // RiColorSamples(n, nRGB, RGBn);

  return TCL_OK;
}


static int
cmd_RiOption(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]";
  int	num_args = 2, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;




  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiOption : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiOptionV((RtToken)argv[1], n, tokens, parms);

  newRIBCommand = [[RIBOption alloc] init];
  [newRIBCommand setName:argv[1]
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiAttributeBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newShape, newRIBCommand;
  static char  nameBuf[64];


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me evaluatingEveProc] || ![me treatAttributeBeginLikeStartShape])
  {  newRIBCommand = [[RIBAttributeBegin alloc] init];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }

  newShape = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]];
  sprintf(nameBuf, "changeMyNamePlease%d", ([me uniqueTag]));
  [newShape setShapeName:nameBuf];
  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartRootShape(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "shapeName";
  int	num_args = 2;
  id    newShape;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  newShape = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]];
  [newShape setShapeName:argv[1]];
  [me setTmpRootShape:newShape];
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_InstallRootShape(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  [me installRootShapeInWell];

  return TCL_OK;
}


static int
cmd_StartShape(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "shapeName [{transformationMatrix}]", **argv2;
  int	argc2, i, j, cnt = 0;
  id    newShape, newRIBCommand;
  RtMatrix  transformMatrix;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ((argc != 2) && (argc != 3))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, 
		"%s : problem splitting <%s> as a list", 
		argv[0], argv[2]);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     if (argc2 != 16)
     {  sprintf(errBuf, 
		"USAGE: %s %s\n4x4matrix should have 16 elements, not %d", 
		argv[0], my_args, argc2);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
	{  transformMatrix[i][j] = (RtFloat)atof(argv2[cnt++]);
        }
     }
     free(argv2);
  } 

  if ([me evaluatingEveProc])
  {  if (argc == 3)
     {  NXLogError("warning: using a startShape command inside an EveProc: ");
        NXLogError("should be using a RIBAttributeBegin and RIBConcatTransform objects instead of a WW3DShape,");
        NXLogError("but right now, I'm ignoring the matrix and merely substituting a RIBAttributeBegin object...");
        newRIBCommand = [[RIBAttributeBegin alloc] init];
        [newRIBCommand setMyShape:[me currentShape]];
        [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  NXLogError("warning: using a startShape command inside an EveProc: using a RIBAttributeBegin object instead of a WW3DShape...");
        newRIBCommand = [[RIBAttributeBegin alloc] init];
        [newRIBCommand setMyShape:[me currentShape]];
        [me setTmpRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }

  if ([me evaluatingEveProc])
  {  sprintf(errBuf, "you cannot nest a startShape call inside an EveProc call - try an AttributeBegin/End pair instead");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  newShape = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]];
  [newShape setShapeName:argv[1]];
  if (argc == 3)
  {  [newShape setTransformMatrix:transformMatrix];
  }

  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartLight(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "lightName isGlobal";
  int	num_args = 3;
  id    newShape;
  int   globalFlag = 0;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetBoolean(interp, argv[1], &globalFlag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  newShape = [[WW3DLight alloc] init];
  [newShape setShapeName:argv[1]];
  [newShape setGlobal:(BOOL)globalFlag];
  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartAmbientLight(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "lightName intensity isGlobal";
  int	num_args = 4;
  id    newShape;
  int   globalFlag;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetBoolean(interp, argv[3], &globalFlag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[3]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  newShape = [[[WW3DLight alloc] init] makeAmbientWithIntensity:(RtFloat)atof(argv[2])];
  [newShape setShapeName:argv[1]];
  [newShape setGlobal:(BOOL)globalFlag];

  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartDistantLight(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "lightName fromX fromY fromZ toX toY toZ intensity isGlobal";
  int	   num_args = 10;
  id       newShape;
  RtPoint  from, to;
  int      globalFlag = 0;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetBoolean(interp, argv[9], &globalFlag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[9]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  from[0] = (RtFloat)atof(argv[2]);
  from[1] = (RtFloat)atof(argv[3]);
  from[2] = (RtFloat)atof(argv[4]);
  to[0] = (RtFloat)atof(argv[5]);
  to[1] = (RtFloat)atof(argv[6]);
  to[2] = (RtFloat)atof(argv[7]);
  newShape = [[[WW3DLight alloc] init] makeDistantFrom:from to:to intensity:(RtFloat)atof(argv[8])];
  [newShape setShapeName:argv[1]];
  [newShape setGlobal:(BOOL)globalFlag];

  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartPointLight(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "lightName fromX fromY fromZ intensity isGlobal";
  int	   num_args = 7;
  id       newShape;
  RtPoint  from;
  int      globalFlag = 0;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetBoolean(interp, argv[6], &globalFlag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[6]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  from[0] = (RtFloat)atof(argv[2]);
  from[1] = (RtFloat)atof(argv[3]);
  from[2] = (RtFloat)atof(argv[4]);
  newShape = [[[WW3DLight alloc] init] makePointFrom:from intensity:(RtFloat)atof(argv[4])];
  [newShape setShapeName:argv[1]];
  [newShape setGlobal:(BOOL)globalFlag];

  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_StartSpotLight(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "lightName fromX fromY fromZ toX toY toZ coneAngle coneDelta beamDistribution intensity isGlobal";
  int	   num_args = 13;
  id       newShape;
  RtPoint  from, to;
  int      globalFlag = 0;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetBoolean(interp, argv[12], &globalFlag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[12]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setRiBegun:YES];
  from[0] = (RtFloat)atof(argv[2]);
  from[1] = (RtFloat)atof(argv[3]);
  from[2] = (RtFloat)atof(argv[4]);
  to[0] = (RtFloat)atof(argv[5]);
  to[1] = (RtFloat)atof(argv[6]);
  to[2] = (RtFloat)atof(argv[7]);
  newShape = [[[WW3DLight alloc] init] makeSpotFrom:from to:to 
 	                                  coneAngle:(RtFloat)atof(argv[8]) 
	                                  coneDelta:(RtFloat)atof(argv[9]) 
	                                  beamDistribution:(RtFloat)atof(argv[10]) 
	                                  intensity:(RtFloat)atof(argv[11])];
  [newShape setShapeName:argv[1]];
  [newShape setGlobal:(BOOL)globalFlag];

  if ([me currentShape])
  {  [[me currentShape] addChild:newShape];
  }
  else
  {  [me setTmpRootShape:newShape];
  }
  [me setCurrentShape:newShape];

  return TCL_OK;
}


static int
cmd_EndShape(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me evaluatingEveProc])
  {  newRIBCommand = [[RIBAttributeEnd alloc] init];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }

  // at this point, calculate bounding box of current shape
  //[[me currentShape] logTransformWithMsg:"AttributeEnd before boundingBox calc"];
  [[me currentShape]  calculateBoundingBoxStartingAt:[[me sceneClock] timestamp] endingAt:[[me sceneClock] timestamp]]; 
  //[[me currentShape] logTransformWithMsg:"AttributeEnd after boundingBox calc"];
  [me setCurrentShape:[[me currentShape] parent]];

  return TCL_OK;
}


static int
cmd_RiAttributeEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me evaluatingEveProc] || ![me treatAttributeBeginLikeStartShape])
  {  newRIBCommand = [[RIBAttributeEnd alloc] init];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }

  // at this point, calculate bounding box of current shape
  //[[me currentShape] logTransformWithMsg:"AttributeEnd before boundingBox calc"];
  [[me currentShape]  calculateBoundingBoxStartingAt:[[me sceneClock] timestamp] endingAt:[[me sceneClock] timestamp]]; 
  //[[me currentShape] logTransformWithMsg:"AttributeEnd after boundingBox calc"];
  [me setCurrentShape:[[me currentShape] parent]];

  return TCL_OK;
}


static int
cmd_RiColor(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "{red green blue}|red green blue", **argv2;
  int	   argc2;
  RtColor  aColor;
  id       newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreColors])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != 2) && (argc != 4))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 2)
  {  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, 
   	        "USAGE: %s : problem splitting <%s> as a list", 
		argv[0], argv[1]);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     if (argc2 != 3)
     {  sprintf(errBuf, 
   	        "USAGE: %s %s\ncolor should have 3 elements, not %d", 
		argv[0], my_args, argc2);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     aColor[0] = (RtFloat)atof(argv2[0]);
     aColor[1] = (RtFloat)atof(argv2[1]);
     aColor[2] = (RtFloat)atof(argv2[2]);
     free(argv2);
  }
  else
  {  aColor[0] = (RtFloat)atof(argv[1]);
     aColor[1] = (RtFloat)atof(argv[2]);
     aColor[2] = (RtFloat)atof(argv[3]);
  }

  newRIBCommand = [[RIBColor alloc] init];
  [newRIBCommand setRtColor:aColor];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiOpacity(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "{red green blue}|red green blue", **argv2;
  int	   argc2;
  RtColor  anOpacity;
  id       newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreColors])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != 2) && (argc != 4))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 2)
  {  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, 
   	        "%s : problem splitting <%s> as a list", 
		argv[0], argv[1]);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     if (argc2 != 3)
     {  sprintf(errBuf, 
   	        "USAGE: %s %s\nOpacity should have 3 elements, not %d", 
		argv[0], my_args, argc2);
	Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     anOpacity[0] = (RtFloat)atof(argv2[0]);
     anOpacity[1] = (RtFloat)atof(argv2[1]);
     anOpacity[2] = (RtFloat)atof(argv2[2]);
     free(argv2);
  }
  else
  {  anOpacity[0] = (RtFloat)atof(argv[1]);
     anOpacity[1] = (RtFloat)atof(argv[2]);
     anOpacity[2] = (RtFloat)atof(argv[3]);
  }

  newRIBCommand = [[RIBOpacity alloc] init];
  [newRIBCommand setOpacity:anOpacity];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiTextureCoordinates(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "s1 t1 s2 t2 s3 t3 s4 t4";
  int	num_args = 9;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiTextureCoordinates((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), 
  //		       (RtFloat)atof(argv[3]), (RtFloat)atof(argv[4]), 
  //		       (RtFloat)atof(argv[5]), (RtFloat)atof(argv[6]), 
  //		       (RtFloat)atof(argv[7]), (RtFloat)atof(argv[8]));

  newRIBCommand = [[RIBTextureCoordinates alloc] init];
  [newRIBCommand setS1:(RtFloat)atof(argv[1]) t1:(RtFloat)atof(argv[2])
                    s2:(RtFloat)atof(argv[3]) t2:(RtFloat)atof(argv[4])
                    s3:(RtFloat)atof(argv[5]) t3:(RtFloat)atof(argv[6])
                    s4:(RtFloat)atof(argv[7]) t4:(RtFloat)atof(argv[8])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


RIB_light_t
*getRIBLightGivenToken(me, token)
WWEveParser  *me;
RtToken      token;
{
  int        i, howMany = list_size(me->rib_light_list);
  RIB_light_t  *aRIBLight;


  for (i = 0; i < howMany; i++)
  {  aRIBLight = (RIB_light_t *)list_get_nth(me->rib_light_list, i);
     if (aRIBLight->token == token)
     {  return (aRIBLight);
     }
  }
  for (i = 0; i < howMany; i++)
  {  aRIBLight = (RIB_light_t *)list_get_nth(me->rib_light_list, i);
     if (!strcmp(aRIBLight->token, token))
     {  return (aRIBLight);
     }
  }
  return (RIB_light_t *)NULL;
}


static int
cmd_RiIlluminate(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "token [1|0]";
  int	       num_args = 3;
  RIB_light_t  *aRIBLight;
  int          flag = 0;
  id           newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) || (strcmp(argv[2], "0") && strcmp(argv[2], "1")))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (!(aRIBLight = getRIBLightGivenToken(me, argv[1])))
  {  sprintf(errBuf, "token %s doesn't correspond to a defined light", argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  
  //if (!strcmp(argv[2], "1"))
  //{  RiIlluminate(aRIBLight->handle, RI_TRUE);
  //}
  //else
  //{  RiIlluminate(aRIBLight->handle, RI_FALSE);
  //}

  if (Tcl_GetBoolean(interp, argv[2], &flag) != TCL_OK)
  {  sprintf(errBuf, "%s isn't a valid boolean value", argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[RIBIlluminate alloc] init];
  [newRIBCommand setToken:aRIBLight->token flag:(RtBoolean)flag];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiShadingInterpolation(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "constant|smooth";
  int	num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) && strcmp(argv[1], "constant") && strcmp(argv[1], "smooth")) 
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (!strcmp(argv[1], "constant"))
  {  // RiShadingInterpolation(RI_CONSTANT);
  }
  if (!strcmp(argv[1], "smooth"))
  {  // RiShadingInterpolation(RI_SMOOTH);
  }

  return TCL_OK;
}

static int
cmd_RiShadingRate(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "shadingRate";
  int	num_args = 2;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me ignoreShadingRate])
  {  return TCL_OK;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //[[me currentShape] logTransformWithMsg:"Translate before"];
  if ([me firmTransforms])
  {  [[me currentShape] preTranslate:(RtFloat)atof(argv[1]) :(RtFloat)atof(argv[2]) :(RtFloat)atof(argv[3])];
     //[[me currentShape] logTransformWithMsg:"Translate (firmed) after"];
     return TCL_OK;
  }

  newRIBCommand = [[RIBShadingRate alloc] init];
  [newRIBCommand setShadingRate:(RtFloat)atof(argv[1])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"Translate after"];
  return TCL_OK;
}



static int
cmd_RiMatte(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "on|off";
  int	num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) && strcmp(argv[1], "on") && strcmp(argv[1], "off")) 
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (!strcmp(argv[1], "on"))
  {  // RiMatte(RI_TRUE);
  }
  if (!strcmp(argv[1], "off"))
  {  // RiMatte(RI_FALSE);
  }

  return TCL_OK;
}


static int
cmd_RiBound(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "{xmin xmax ymin ymax zmin zmax}", 
           **argv2;
  int	   num_args = 2,
           argc2;
  RtBound  bbox;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, 
	     "%s : problem splitting <%s> as a list", 
	     argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != 6)
  {  sprintf(errBuf, 
	     "USAGE: %s %s\nRiBound vector should have 6 elements, not %d", 
	     argv[0], my_args, argc2);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  bbox[0] = (RtFloat)atof(argv2[0]);
  bbox[1] = (RtFloat)atof(argv2[1]);
  bbox[2] = (RtFloat)atof(argv2[2]);
  bbox[3] = (RtFloat)atof(argv2[3]);
  bbox[4] = (RtFloat)atof(argv2[4]);
  bbox[5] = (RtFloat)atof(argv2[5]);

  // RiBound(bbox);

  return TCL_OK;
}


static int
cmd_RiGeometricApproximation(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "flatness value";
  int	num_args = 3;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiGeometricApproximation(argv[1], (RtFloat)atof(argv[2]));

  return TCL_OK;
}


static int
cmd_RiOrientation(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "inside|outside|lh|rh";
  int	num_args = 4;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) && strcmp(argv[1], "inside") && strcmp(argv[1], "outside") && strcmp(argv[1], "lh") && strcmp(argv[1], "rh")) 
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiOrientation(getTokenGivenName(me, argv[1]));

  return TCL_OK;
}

static int
cmd_RiReverseOrientation(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiReverseOrientation();

  return TCL_OK;
}


static int
cmd_RiSides(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "1|2";
  int	num_args = 2;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) && (strcmp(argv[1], "1")) && (strcmp(argv[1], "2")))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[RIBSides alloc] init];
  [newRIBCommand setSides:atoi(argv[1])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  
     [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiIdentity(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me firmTransforms])
  {  
     [[me currentShape] setTransformMatrix:(RtFloat (*)[4])N3DIdentityMatrix];
     return TCL_OK;
  }

  newRIBCommand = [[RIBIdentity alloc] init];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  return TCL_OK;
}


static int
cmd_RiTransform(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char      *my_args = "4x4matrix", **argv2;
  int	    num_args = 2, argc2, i, j, cnt = 0;
  RtMatrix  transformMatrix;
  id        newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, 
	     "%s : problem splitting <%s> as a list", 
	     argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != 16)
  {  sprintf(errBuf, 
	     "USAGE: %s %s\n4x4matrix should have 16 elements, not %d", 
	     argv[0], my_args, argc2);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  for (i = 0; i < 4; i++)
  {  for (j = 0; j < 4; j++)
     {  transformMatrix[i][j] = (RtFloat)atof(argv2[cnt++]);
     }
  }
  free(argv2);

  //[[me currentShape] logTransformWithMsg:"Transform before"];
  if ([me firmTransforms])
  {  [[me currentShape] setTransformMatrix:transformMatrix];
     //[[me currentShape] logTransformWithMsg:"Transform (firmed) after"];
     return TCL_OK;
  }
  newRIBCommand = [[RIBTransform alloc] init];
  [newRIBCommand setMatrix:transformMatrix];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"Transform after"];
  return TCL_OK;
}


static int
cmd_RiConcatTransform(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char      *my_args = "4x4matrix", **argv2;
  int	    num_args = 2, argc2, i, j, cnt = 0;
  RtMatrix  transformMatrix;
  id        newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, 
	     "%s : problem splitting <%s> as a list", 
	     argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc2 != 16)
  {  sprintf(errBuf, 
	     "USAGE: %s %s\n4x4matrix should have 16 elements, not %d", 
	     argv[0], my_args, argc2);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  for (i = 0; i < 4; i++)
  {  for (j = 0; j < 4; j++)
     {  transformMatrix[i][j] = (RtFloat)atof(argv2[cnt++]);
     }
  }
  free(argv2);

  //[[me currentShape] logTransformWithMsg:"ConcatTransform before"];
  if ([me firmTransforms])
  {  [[me currentShape] concatTransformMatrix:transformMatrix premultiply:YES];
     //[[me currentShape] logTransformWithMsg:"ConcatTransform (firmed) after"];
     return TCL_OK;
  }

  newRIBCommand = [[RIBConcatTransform alloc] init];
  [newRIBCommand setMatrix:transformMatrix];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"ConcatTransform after"];
  return TCL_OK;
}


static int
cmd_RiPerspective(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "fov";
  int	num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiPerspective((RtFloat)atof(argv[1]));
  //newRIBCommand = [[RIBPerspective alloc] init];
  //[newRIBCommand setMyShape:[me currentShape]];
  //[[me currentShape] appendRIBCommand:newRIBCommand];

  return TCL_OK;
}



// should also allow a list as arg[1]
static int
cmd_RiTranslate(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "dx dy dz";
  int	num_args = 4;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //[[me currentShape] logTransformWithMsg:"Translate before"];
  if ([me firmTransforms])
  {  [[me currentShape] preTranslate:(RtFloat)atof(argv[1]) :(RtFloat)atof(argv[2]) :(RtFloat)atof(argv[3])];
     //[[me currentShape] logTransformWithMsg:"Translate (firmed) after"];
     return TCL_OK;
  }

  newRIBCommand = [[RIBTranslate alloc] init];
  [newRIBCommand setDX:(RtFloat)atof(argv[1]) dy:(RtFloat)atof(argv[2]) dz:(RtFloat)atof(argv[3])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"Translate after"];
  return TCL_OK;
}


static int
cmd_RiRotate(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "angle dx dy dz";
  int	   num_args = 5;
  id       newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //[[me currentShape] logTransformWithMsg:"Rotate before"];
  if ([me firmTransforms])
  {  RtPoint  axis;

     axis[0] = (RtFloat)atof(argv[2]);
     axis[1] = (RtFloat)atof(argv[3]);
     axis[2] = (RtFloat)atof(argv[4]);
     [[me currentShape] preRotateAngle:(RtFloat)atof(argv[1]) axis:axis];
     //[[me currentShape] logTransformWithMsg:"Rotate (firmed) after"];
     return TCL_OK;
  }

  newRIBCommand = [[RIBRotate alloc] init];
  [newRIBCommand setAngle:(RtFloat)atof(argv[1]) dx:(RtFloat)atof(argv[2]) dy:(RtFloat)atof(argv[3]) dz:(RtFloat)atof(argv[4])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  { [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"Rotate after"];
  return TCL_OK;
}


static int
cmd_RiScale(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "sx sy sz";
  int	num_args = 4;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //[[me currentShape] logTransformWithMsg:"Scale before"];
  if ([me firmTransforms])
  {  [[me currentShape] preScale:(RtFloat)atof(argv[1]) :(RtFloat)atof(argv[2]) :(RtFloat)atof(argv[3])];
     //[[me currentShape] logTransformWithMsg:"Scale (firmed) after"];
     return TCL_OK;
  }

  newRIBCommand = [[RIBScale alloc] init];
  [newRIBCommand setSX:(RtFloat)atof(argv[1]) sy:(RtFloat)atof(argv[2]) sz:(RtFloat)atof(argv[3])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  //[[me currentShape] logTransformWithMsg:"Scale after"];
  return TCL_OK;
}


static int
cmd_RiSkew(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "angle x1 y1 z1 x2 y2 z2"; // or "angle {x1 y1 z1} {x2 y2 z2}"
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //if ((argc < 8) && (argc != 4))
  if (argc != 8)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[RIBSkew alloc] init];
  [newRIBCommand setAngle:(RtFloat)atof(argv[1]) 
                    dx1:(RtFloat)atof(argv[2]) dy1:(RtFloat)atof(argv[3]) dz1:(RtFloat)atof(argv[4])
                    dx2:(RtFloat)atof(argv[5]) dy2:(RtFloat)atof(argv[6]) dz2:(RtFloat)atof(argv[7])];

  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiCoordinateSystem(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name";
  int	num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiCoordinateSystem((RtToken)argv[1]);

  return TCL_OK;
}



static int
cmd_RiTransformBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newShape, newRIBCommand;
  static char  nameBuf[64];


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me treatTransformBeginLikeAttributeBegin] && [me treatAttributeBeginLikeStartShape])
  {  newShape = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]];
     sprintf(nameBuf, "xformChangeMyNamePlease%d", ([me uniqueTag]));
     [newShape setShapeName:nameBuf];
     if ([me currentShape])
     {  [[me currentShape] addChild:newShape];
     }
     else
     {  [me setTmpRootShape:newShape];
     }
     [me setCurrentShape:newShape];
  }
  else
  {  newRIBCommand = [[RIBTransformBegin alloc] init];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
  }
  return TCL_OK;
}


static int
cmd_RiTransformEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me treatTransformBeginLikeAttributeBegin] && [me treatAttributeBeginLikeStartShape])
  {  //[[me currentShape] logTransformWithMsg:"TransformEnd (like AttributeEnd) before boundingBox calc"];
     [[me currentShape]  calculateBoundingBoxStartingAt:[[me sceneClock] timestamp] endingAt:[[me sceneClock] timestamp]]; 
     //[[me currentShape] logTransformWithMsg:"TransformEnd (like AttributeEnd) after boundingBox calc"];
     [me setCurrentShape:[[me currentShape] parent]];
  }
  else
  {  newRIBCommand = [[RIBTransformEnd alloc] init];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
  }
  
  return TCL_OK;
}


static int
cmd_RiAttribute(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]";
  int	num_args = 2, n, i;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  static char  noQuoteBuf[1024];
    

  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiAttribute : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // need to strip out double quotes, which will probably be in the beginning and end of the string.
  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiAttributeV(argv[1], n, tokens, parms);
  i = 1;
  while (i < argc)
  {  if (!strcmp(argv[i], "identifier"))
     {  if (!strcmp(argv[i+1], "name"))
        {  if (*(argv[i+2]) == '\"')
           {  int cnt = 1;
              while ( (*((argv[i+2]) + cnt)) && (*((argv[i+2]) +cnt) != '\"'))  
              {  noQuoteBuf[cnt - 1] = *((argv[i+2]) + cnt);
	      }
              [[me currentShape] setShapeName:noQuoteBuf];
 	   }
           else
           {  [[me currentShape] setShapeName:argv[i+2]];
           }
        }
        if (!strcmp(argv[i+1], "part"))
        {  if (*(argv[i+2]) == '\"')
           {  int cnt = 1;
              while ( (*((argv[i+2]) + cnt)) && (*((argv[i+2]) +cnt) != '\"'))  
              {  noQuoteBuf[cnt - 1] = *((argv[i+2]) + cnt);
	      }
              [[me currentShape] setShapeName:noQuoteBuf];
 	   }
           else
           {  [[me currentShape] setShapeName:argv[i+2]];
           }
        }
        if (!strcmp(argv[i+1], "shadinggroup"))
        {  if (*(argv[i+2]) == '\"')
           {  int cnt = 1;
              while ( (*((argv[i+2]) + cnt)) && (*((argv[i+2]) +cnt) != '\"'))  
              {  noQuoteBuf[cnt - 1] = *((argv[i+2]) + cnt);
	      }
              [[me currentShape] setShadingGroup:noQuoteBuf];
 	   }
           else
           {  [[me currentShape] setShadingGroup:argv[i+2]];
           }
        }
        if (!strcmp(argv[i+1], "geometrygroup"))
        {  if (*(argv[i+2]) == '\"')
           {  int cnt = 1;
              while ( (*((argv[i+2]) + cnt)) && (*((argv[i+2]) +cnt) != '\"'))  
              {  noQuoteBuf[cnt - 1] = *((argv[i+2]) + cnt);
	      }
              [[me currentShape] setGeometryGroup:noQuoteBuf];
 	   }
           else
           {  [[me currentShape] setGeometryGroup:argv[i+2]];
           }
        }
        if (!strcmp(argv[i+1], "materialgroup"))
        {  if (*(argv[i+2]) == '\"')
           {  int cnt = 1;
              while ( (*((argv[i+2]) + cnt)) && (*((argv[i+2]) +cnt) != '\"'))  
              {  noQuoteBuf[cnt - 1] = *((argv[i+2]) + cnt);
	      }
              [[me currentShape] setMaterialGroup:noQuoteBuf];
 	   }
           else
           {  [[me currentShape] setMaterialGroup:argv[i+2]];
           }
        }
     }
     i += 3;
  }
  
  newRIBCommand = [[RIBAttribute alloc] init];
  [newRIBCommand setName:argv[1]
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


int
isPredefinedBasis(name)
char *name;
{
  if (!strcmp("bezier", name)) { return 1; }
  if (!strcmp("b-spline", name)) { return 1; }
  if (!strcmp("catmull-rom", name)) { return 1; }
  if (!strcmp("hermite", name)) { return 1; }
  if (!strcmp("power", name)) { return 1; }
  return 0;
}

RtInt
stepForPredefinedBasis(name)
char *name;
{
  if (!strcmp("bezier", name)) { return RI_BEZIERSTEP; }
  if (!strcmp("b-spline", name)) { return RI_BSPLINESTEP; }
  if (!strcmp("catmull-rom", name)) { return RI_CATMULLROMSTEP; }
  if (!strcmp("hermite", name)) { return RI_HERMITESTEP; }
  if (!strcmp("power", name)) { return RI_POWERSTEP; }
  return 0;
}

/* return 1 on successful copy */
int
basisCpy(name, basis)
char *name;
RtBasis *basis;
{
  int i, j;


  if (!isPredefinedBasis(name)) { return 0; }

  if (!strcmp("bezier", name))
  {  for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  (*basis)[i][j] = RiBezierBasis[i][j];
        }
     } 
     return 1;
  }
  if (!strcmp("b-spline", name))
  {  for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  (*basis)[i][j] = RiBSplineBasis[i][j];
        }
     } 
     return 1;
  }
  if (!strcmp("catmull-rom", name))
  {  for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  (*basis)[i][j] = RiCatmullRomBasis[i][j];
        }
     } 
     return 1;
  }
  if (!strcmp("hermite", name))
  {  for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  (*basis)[i][j] = RiHermiteBasis[i][j];
        }
     } 
     return 1;
  }
  if (!strcmp("power", name))
  {  for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  (*basis)[i][j] = RiPowerBasis[i][j];
        }
     } 
     return 1;
  }

  return 0;  
}



static int
cmd_RiBasis(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char     *my_args = "ubasis ustep vbasis vstep", **argv2;
  int	   num_args = 5, i, j, cnt, argc2;
  RtBasis  uBasis, vBasis;
  RtInt    uStep, vStep;
  id       newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  /* uBasis */
  if (!isPredefinedBasis(argv[1]))
  {  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, 
		"%s : problem splitting <%s> as a list",
		argv[0], argv[1]);
       Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     if (argc2 != 16)
     {  sprintf(errBuf, 
		"USAGE: %s %s\nuBasis should be one of the predefined bases (bezier, b-spline, catmull-rom, hermite, power) or have 16 elements, not %d", 
		argv[0], my_args, argc2);
       Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     cnt = 0;
     for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  uBasis[i][j] = (RtFloat)atof(argv2[cnt++]);
        }
     }
     free(argv2);
     uStep = (RtInt)atoi(argv[2]);
  }
  else
  {  if (!basisCpy(argv[1], &uBasis))
     {  sprintf(errBuf, "RiBasis : unable to copy predefined uBasis %s", argv[1]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     uStep = stepForPredefinedBasis(argv[1]);
  }

  /* vBasis */
  if (!isPredefinedBasis(argv[3]))
  {  if (Tcl_SplitList(interp, argv[3], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, 
		"%s : problem splitting <%s> as a list",
		argv[0], argv[3]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     if (argc2 != 16)
     {  sprintf(errBuf, 
		"USAGE: %s %s\nvBasis should be one of the predefined bases (bezier, b-spline, catmull-rom, hermite, power) or have 16 elements, not %d", 
		argv[0], my_args, argc2);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     cnt = 0;
     for (i = 0; i < 4; i++)
     {  for (j = 0; j < 4; j++)
        {  vBasis[i][j] = (RtFloat)atof(argv2[cnt++]);
        }
     }
     free(argv2);
     vStep = (RtInt)atoi(argv[2]);
  }
  else
  {  if (!basisCpy(argv[3], &vBasis))
     {  sprintf(errBuf, "RiBasis : unable to copy predefined vBasis %s", argv[3]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }
     vStep = stepForPredefinedBasis(argv[3]);
  }

  // RiBasis(uBasis, uStep, vBasis, vStep);
  newRIBCommand = [[RIBBasis alloc] init];
  [newRIBCommand setUBasis:uBasis uBasisToken:getTokenGivenName(me, argv[1]) uStep:uStep 
                    vBasis:vBasis vBasisToken:getTokenGivenName(me, argv[3]) vStep:vStep];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  
     [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiSolidBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "primitive|intersection|union|difference";
  int	num_args = 2;
  id       newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc != num_args) || ((strcmp(argv[1], "primitive")) && (strcmp(argv[1], "intersection")) && (strcmp(argv[1], "union")) && (strcmp(argv[1], "difference"))))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiSolidBegin(getTokenGivenName(me, argv[1]));

  newRIBCommand = [[RIBSolidBegin alloc] init];
  [newRIBCommand setOperation:getTokenGivenName(me, argv[1])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  
     [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  return TCL_OK;
}


static int
cmd_RiSolidEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiSolidEnd();

  newRIBCommand = [[RIBSolidEnd alloc] init];
  [newRIBCommand setMyShape:[me currentShape]];

  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  
     [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiMakeTexture(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char       *my_args = "pictureName textureName sWrap tWrap filterFuncName sWidth tWidth [parameterList]";
  int	     num_args = 8, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc) % 2)
  {  sprintf(errBuf, "RiMakeTexture : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  newRIBCommand = [[RIBMakeTexture alloc] init];
  [newRIBCommand setPictureName:(const char *)argv[1] textureName:(const char *)argv[2]
                 sWrap:(RtToken)argv[3] tWrap:(RtToken)argv[4] filterFuncName:(const char *)argv[5]
                 sWidth:(RtFloat)atof(argv[6]) tWidth:(RtFloat)atof(argv[7])];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiMotionBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char   *my_args = "{t0 t1 ... tn}";
  id     newRIBCommand;
  char   **argv2 = NULL;
  int	 argc2, i;
  float  *times;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 1)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  times = (float *)malloc(sizeof(float)*argc2);
  for (i = 0; i < argc2; i++)
  {  times[i] = (float)atof(argv2[i]);
  }
  newRIBCommand = [[RIBMotionBegin alloc] init];
  [newRIBCommand setNTimes:argc2 timeVector:times];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  
     [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  return TCL_OK;
}



static int
cmd_RiMotionEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;
  id    newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[RIBMotionEnd alloc] init];
  [newRIBCommand setMyShape:[me currentShape]];
  [[me currentShape] appendRIBCommand:newRIBCommand];

  return TCL_OK;
}


RIB_object_t
*getRIBObjectGivenTag(me, tag)
WWEveParser  *me;
int           tag;
{
  int        i, howMany = list_size(me->rib_object_list);
  RIB_object_t  *aRIBObject;


  for (i = 0; i < howMany; i++)
  {  aRIBObject = (RIB_object_t *)list_get_nth(me->rib_object_list, i);
     if (aRIBObject->tag == tag)
     {  return (aRIBObject);
     }
  }
  return (RIB_object_t *)NULL;
}


static int
cmd_RiObjectBegin(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char          *my_args = "tag";
  int	        num_args = 2, tag;
  RIB_object_t  *aRIBObject;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  tag = atoi(argv[1]);
  /* need to make sure that an object tagged with this object's tag
     doesn't already exist */
  if (getRIBObjectGivenTag(me, tag))
  {  sprintf(errBuf, "tag %d already in use", tag);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  aRIBObject = (RIB_object_t *)malloc(sizeof(RIB_object_t));
  if (!aRIBObject)
  {  sprintf(errBuf, "RiObjectBegin : unable to malloc memory for RIB object"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }

  aRIBObject->tag = tag;
  // aRIBObject->handle = RiObjectBegin();

  list_put(me->rib_object_list, aRIBObject);

  sprintf(errBuf, "%d", aRIBObject->tag);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);

  return TCL_OK;
}


static int
cmd_RiObjectEnd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "";
  int	num_args = 1;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiObjectEnd();

  return TCL_OK;
}


static int
cmd_RiObjectInstance(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char          *my_args = "tag";
  int	        num_args = 2, tag;
  RIB_object_t  *aRIBObject;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  tag = atoi(argv[1]);
  if (!(aRIBObject = getRIBObjectGivenTag(me, tag)))
  {  sprintf(errBuf, "tag %d doesn't correspond to a defined object", tag);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // RiObjectInstance(aRIBObject->handle);

  return TCL_OK;
}


/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/*           "when the going gets weird, the weird turn pro"              */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/

/* The following section has all the RenderMan commands  */
/* with the ubiquitous parameterlist                     */

static int
cmd_RiImager(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]";
  int	num_args = 2, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;





  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiImager : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiImagerV(argv[1], n, tokens, parms);

  return TCL_OK;
}


static int
cmd_RiHider(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "type [parameterlist]";
  int	num_args = 2, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;





  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiHider : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiHiderV(argv[1], n, tokens, parms);

  return TCL_OK;
}


static int
cmd_RiLightSource(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "shaderName token [parameterlist]", **argv2 = NULL;
  int	       num_args = 3, n, argc2;
  RtToken      *tokens = (RtToken *)RI_NULL;
  RtPointer    *parms = (RtPointer *)RI_NULL;
  int          *nVector = NULL, 
               *typeVector = NULL;
  char         **archiveVector = NULL;
  RIB_light_t  *aRIBLight;
  id           newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders] || [me ignoreLights])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 4)
  {  if (Tcl_SplitList(interp, argv[3], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[3]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiLightSource : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if ((argc+1) % 2)
     {  sprintf(errBuf, 
		"RiLightSource : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
        if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
        {  return TCL_ERROR;
        }
     }
  }


  aRIBLight = (RIB_light_t *)malloc(sizeof(RIB_light_t));
  if (!aRIBLight)
  {  sprintf(errBuf, "RiLightSource : unable to malloc memory for RIB light"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }

  aRIBLight->token = RiCreateHandle(argv[2], RI_LIGHTSOURCE);
  if (getRIBLightGivenToken(me, aRIBLight->token))
  {  fprintf(stderr, "WARNING: RiLightSource : token %s already in use - overwriting...\n", aRIBLight->token);
  }

  list_put(me->rib_light_list, aRIBLight);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms 
	                          archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];

  [newShader setToken:aRIBLight->token];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  //[[me currentShape] setShader_:newShader];
        // this tickles a nasty bug in NeXT's 3DKit...
        [[me currentShape] appendRIBCommand:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  sprintf(errBuf, "%d", (int)aRIBLight->token);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);

  return TCL_OK;
}


static int
cmd_RiAreaLightSource(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char         *my_args = "shaderName token [parameterlist]", **argv2 = NULL;
  int	       num_args = 3, n, argc2;
  RtToken      *tokens = (RtToken *)RI_NULL;
  RtPointer    *parms = (RtPointer *)RI_NULL;
  int          *nVector = NULL, 
               *typeVector = NULL;
  char         **archiveVector = NULL;
  RIB_light_t  *aRIBLight;
  id           newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders] || [me ignoreLights])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 4)
  {  if (Tcl_SplitList(interp, argv[3], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[3]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiLightSource : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if ((argc+1) % 2)
     {  sprintf(errBuf, 
		"RiLightSource : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
        if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
        {  return TCL_ERROR;
        }
     }
  }


  aRIBLight = (RIB_light_t *)malloc(sizeof(RIB_light_t));
  if (!aRIBLight)
  {  sprintf(errBuf, "RiLightSource : unable to malloc memory for RIB light"); 
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return 0;
  }

  aRIBLight->token = RiCreateHandle(argv[2], RI_LIGHTSOURCE);
  if (getRIBLightGivenToken(me, aRIBLight->token))
  {  fprintf(stderr, "WARNING: RiLightSource : token %s already in use - overwriting...\n", aRIBLight->token);
  }

  list_put(me->rib_light_list, aRIBLight);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms 
	                          archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];

  [newShader setToken:aRIBLight->token];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  //[[me currentShape] setShader_:newShader];
        // this tickles a nasty bug in NeXT's 3DKit...
        [[me currentShape] appendRIBCommand:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  sprintf(errBuf, "%d", (int)aRIBLight->token);
  Tcl_AppendResult(interp, errBuf, (char *)NULL);

  return TCL_OK;
}


static int
cmd_RiSurface(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiSurface : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiSurface : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiSurfaceV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  if (argv2)
  {  free(argv2);
  }

  return TCL_OK;
}


static int
cmd_RiAtmosphere(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiAtmosphere : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiAtmosphere : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiAtmosphereV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  return TCL_OK;
}


static int
cmd_RiInterior(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiInterior : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiInterior : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiInteriorV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  return TCL_OK;
}


static int
cmd_RiExterior(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); 
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiExterior : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiExterior : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiExteriorV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  return TCL_OK;
}


static int
cmd_RiDeformation(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }
 
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiDeformation list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiDeformation : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiDeformationV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  return TCL_OK;
}


static int
cmd_RiDisplacement(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "name [parameterlist]", **argv2 = NULL;
  int	num_args = 2, n, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newShader;
 

  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ([me ignoreShaders])
  {  return TCL_OK;
  }

  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
     {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     if (argc2 % 2)
     {  if (argv2) 
        {  free(argv2); 
        }
        sprintf(errBuf, 
		"RiDisplacement : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }

     n = argc2 / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, 0, argv2))
     {  return TCL_ERROR;
     }
  }
  else
  {  if (argc % 2)
     {  sprintf(errBuf, "RiDisplacement : parameter list must be in groups of two, i.e. the number of args is an even number");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
	return TCL_ERROR;
     }

     n = 0;
     if (argc > num_args)
     {  n = (argc - num_args) / 2;
	if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
	{  return TCL_ERROR;
	}
     }
  }
  // RiDisplacementV(argv[1], n, tokens, parms);

  newShader = [[WW3DShader alloc] initWithShader:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newShader];
  }
  else
  {  if ([me applyShadersDirectlyToCurrentShape])
     {  [[me currentShape] setShader_:newShader];
     }
     else
     {  [[me currentShape] appendRIBCommand:newShader];
     }
  }

  return TCL_OK;
}


static int
cmd_RiPolygon(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "[parameterlist]", **argv2;
  int	num_args = 1, n, i, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtInt      nVertices;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiPolygon : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  /* need to grovel over parameter list to find "P" to get number of number of vertices */
  nVertices = 0;  i = 1;
  while ((!nVertices) && (i < argc))
  {  if (!strcmp(argv[i], "P"))
     {  if (Tcl_SplitList(interp, argv[i+1], &argc2, &argv2) != TCL_OK)
        {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[i+1]);
           Tcl_AppendResult(interp, errBuf, (char *)NULL);
           return TCL_ERROR;
        }
        if (argv2) { free(argv2); }
	if (argc2 % 3)
        {  sprintf(errBuf, "RiPolygon : the value of the token P must be in 3-vectors - this one has %d elements", argc2);
           Tcl_AppendResult(interp, errBuf, (char *)NULL);
	   return TCL_ERROR;
        }
        nVertices = argc2 / 3;
     }
     i += 2;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiPolygonV(nVertices, n, tokens, parms);

  newRIBCommand = [[RIBPolygon alloc] init];
  [newRIBCommand setNVertices:nVertices n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiGeneralPolygon(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char       *my_args = "nVertices [parameterlist]", 
             **argv2;
  int	     num_args = 2, n, i, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtInt      *nVertices;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiGeneralPolygon : parameter list must be in groups of two : USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  nVertices = (RtInt *)malloc(sizeof(RtInt) * argc2);
  if (!nVertices)
  {  sprintf(errBuf, "RiGeneralPolygon : unable to malloc memory for nVertices");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < argc2; i++)
  {  nVertices[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiGeneralPolygonV((RtInt)argc2, nVertices, n, tokens, parms);
  // free(nVertices);

  newRIBCommand = [[RIBGeneralPolygon alloc] init];
  [newRIBCommand setNLoops:(RtInt)argc2 nVertices:nVertices n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiPointsPolygons(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char       *my_args = "nVertices vertices [parameterlist]", 
             **argv2;
  int	     num_args = 3, n, i, argc2, sum;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
    int      *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtInt      nPolys, *nVertices, *vertices;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiPointsPolygons : parameter list must be in groups of two : USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  /* do nVertices.  should be nPolys long */
  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  nPolys = argc2;
  nVertices = (RtInt *)malloc(sizeof(RtInt) * nPolys);
  if (!nVertices)
  {  sprintf(errBuf, "RiPointsPolygons : unable to malloc memory for nVertices");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  sum = 0;
  for (i = 0; i < nPolys; i++)
  {  nVertices[i] = (RtInt)atoi(argv2[i]);
     sum += nVertices[i];
  }
  free(argv2);

  /* do vertices.  should be nPolys long */
  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != sum)
  {  sprintf(errBuf, 
	     "RiPointsPolygons : the length of vertices must equal to the sum of all the values in the nVertices array :USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  vertices = (RtInt *)malloc(sizeof(RtInt) * argc2);
  if (!vertices)
  {  sprintf(errBuf, "RiPointsPolygons : unable to malloc memory for vertices");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < argc2; i++)
  {  vertices[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiPointsPolygonsV(nPolys, nVertices, vertices, n, tokens, parms);
  // free(nVertices);
  // free(vertices);

  newRIBCommand = [[RIBPointsPolygons alloc] init];
  [newRIBCommand setNPolys:nPolys nVertices:nVertices vertices:vertices n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiPointsGeneralPolygons(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char       *my_args = "nLoops nVertices vertices [parameterlist]", 
             **argv2;
  int	     num_args = 4, n, i, argc2, sum, sum2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtInt      nPolys, *nLoops, *nVertices, *vertices;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, 
	     "parameter list must be in groups of two : USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  /* do nLoops.  should be nPolys long */
  if (Tcl_SplitList(interp, argv[1], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  nPolys = argc2;
  nLoops = (RtInt *)malloc(sizeof(RtInt) * nPolys);
  if (!nLoops)
  {  sprintf(errBuf, "RiPointsGeneralPolygons : unable to malloc memory for nLoops");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  sum = 0;
  for (i = 0; i < nPolys; i++)
  {  nLoops[i] = (RtInt)atoi(argv2[i]);
     sum += nLoops[i];
  }
  free(argv2);

  /* do nVertices.  should be sum long */
  if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != sum)
  {  sprintf(errBuf, 
	     "the length of nVertices must equal to the sum of all the values in the nLoops array :USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  nVertices = (RtInt *)malloc(sizeof(RtInt) * sum);
  if (!nVertices)
  {  sprintf(errBuf, "RiPointsGeneralPolygons : unable to malloc memory for nVertices");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  sum2 = 0;
  for (i = 0; i < sum; i++)
  {  nVertices[i] = (RtInt)atoi(argv2[i]);
     sum2 += nVertices[i];
  }
  free(argv2);

  /* do vertices.  should be sum2 long */
  if (Tcl_SplitList(interp, argv[3], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[3]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != sum2)
  {  sprintf(errBuf, 
	     "the length of vertices must equal to the sum of all the values in the nVertices array :USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  vertices = (RtInt *)malloc(sizeof(RtInt) * argc2);
  if (!vertices)
  {  sprintf(errBuf, "RiPointsGeneralPolygons : unable to malloc memory for vertices");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < argc2; i++)
  {  vertices[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiPointsGeneralPolygonsV(nPolys, nLoops, nVertices, vertices, n, tokens, parms);
  // free(nLoops);
  // free(nVertices);
  // free(vertices);

  newRIBCommand = [[RIBPointsGeneralPolygons alloc] init];
  [newRIBCommand setNPolys:nPolys nLoops:nLoops nVertices:nVertices vertices:vertices n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiPatch(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "bicubic|bilinear [parameterlist]";
  int	num_args = 2, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((strcmp("bicubic", argv[1])) && (strcmp("bilinear", argv[1])))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiPatch : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiPatchV(argv[1], n, tokens, parms);

  newRIBCommand = [[RIBPatch alloc] init];
  [newRIBCommand setType:argv[1] n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiPatchMesh(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "type nU uWrap nV vWrap [parameterlist]";
  int	num_args = 6, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;
  RtToken    uWrap, vWrap;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiPatchMesh : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  uWrap = argv[3];
  if (!strcmp(uWrap, "wrap"))
  {  NXLogError("warning: <wrap> is an undocumented token; substituting <periodic> for uWrap");
     uWrap = RI_PERIODIC;
  }
  else
  {  if (!strcmp(uWrap, "nowrap"))
     {  NXLogError("warning: <nowrap> is an undocumented token; substituting <nonperiodic> for uWrap");
        uWrap = RI_NONPERIODIC;
     }
  }
  vWrap = argv[5];
  if (!strcmp(vWrap, "wrap"))
  {  NXLogError("warning: <wrap> is an undocumented token; substituting <periodic> for vWrap");
     vWrap = RI_PERIODIC;
  }
  else
  {  if (!strcmp(vWrap, "nowrap"))
     {  NXLogError("warning: <nowrap> is an undocumented token; substituting <nonperiodic> for vWrap");
        vWrap = RI_NONPERIODIC;
     }
  }

  if (strcmp(uWrap, "periodic")  && strcmp(uWrap, "nonperiodic"))
  {  sprintf(errBuf, "RiPatchMesh : uWrap must be either periodic or nonperiodic, not <%s>", uWrap);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (strcmp(vWrap, "periodic")  && strcmp(vWrap, "nonperiodic"))
  {  sprintf(errBuf, "RiPatchMesh : vWrap must be either periodic or nonperiodic, not <%s>", vWrap);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiPatchMeshV((RtToken)argv[1], (RtInt)atoi(argv[2]), (RtToken)argv[3], (RtInt)atoi(argv[4]), (RtToken)argv[5], n, tokens, parms);

  newRIBCommand = [[RIBPatchMesh alloc] init];
  [newRIBCommand setType:(RtToken)argv[1] 
                    nU:(RtInt)atoi(argv[2]) uWrap:uWrap
                    nV:(RtInt)atoi(argv[4]) vWrap:vWrap n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiNuPatch(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "nU uOrder uKnot uMin uMax nV vOrder vKnot vMin vMax [parameterlist]", **argv2;
  int	num_args = 11, n, i, argc2;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtInt      nU, nV, uOrder, vOrder, uKnotLength, vKnotLength;
  RtFloat    *uKnot, *vKnot, uMin, uMax, vMin, vMax;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiNuPatch : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  nU = (RtInt)atoi(argv[1]); 
  uOrder = (RtInt)atoi(argv[2]); 
  uMin = (RtFloat)atof(argv[4]); 
  uMax = (RtFloat)atof(argv[5]); 
  uKnotLength = nU + uOrder;

  nV = (RtInt)atoi(argv[6]); 
  vOrder = (RtInt)atoi(argv[7]); 
  vMin = (RtFloat)atof(argv[9]); 
  vMax = (RtFloat)atof(argv[10]); 
  vKnotLength = nV + vOrder;

  if (Tcl_SplitList(interp, argv[3], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[3]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != uKnotLength)
  {  sprintf(errBuf, 
	     "the length of the knots in u must equal to the sum of the order and n :USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  uKnot = (RtFloat *)malloc(sizeof(RtFloat) * uKnotLength);
  if (!uKnot)
  {  sprintf(errBuf, "RiNuPatch : unable to malloc memory for uKnot");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < uKnotLength; i++)
  {  uKnot[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  if (Tcl_SplitList(interp, argv[8], &argc2, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[8]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc2 != vKnotLength)
  {  sprintf(errBuf, 
	     "the length of the knots in v must equal to the sum of the order and n :USAGE: %s %s", 
	     argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  vKnot = (RtFloat *)malloc(sizeof(RtFloat) * vKnotLength);
  if (!vKnot)
  {  sprintf(errBuf, "RiNuPatch : unable to malloc memory for vKnot");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < vKnotLength; i++)
  {  vKnot[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiNuPatchV(nU, uOrder, uKnot, uMin, uMax, nV, vOrder, vKnot, vMin, vMax, n, tokens, parms);

  newRIBCommand = [[RIBNuPatch alloc] init];
  [newRIBCommand setNU:nU uOrder:uOrder uKnot:uKnot uMin:uMin uMax:uMax 
                    nV:nV vOrder:vOrder vKnot:vKnot vMin:vMin vMax:vMax n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiTrimCurve(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "nCurves order knot min max n u v w", **argv2;
  int	num_args = 10, i,  nLoopsI,
        orderLength, nLength, knotLength, minLength, maxLength, uLength, vLength, wLength;
  RtInt      nLoops, *nCurves, *order, *n;
  RtFloat    *knot, *min, *max, *u, *v, *w;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiTrimCurve : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  /* get nLoops and nCurves[] */
  if (Tcl_SplitList(interp, argv[1], &nLoopsI, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[1]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  nLoops = (RtInt)nLoopsI;
  nCurves = (RtInt *)malloc(sizeof(RtInt) * nLoops);
  if (!nCurves)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for nCurves");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < nLoops; i++)
  {  nCurves[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  /* get order[]  */
  if (Tcl_SplitList(interp, argv[2], &orderLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  order = (RtInt *)malloc(sizeof(RtInt) * orderLength);
  if (!order)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for order");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < orderLength; i++)
  {  order[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  /* get knot[]  */
  if (Tcl_SplitList(interp, argv[3], &knotLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[3]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  knot = (RtFloat *)malloc(sizeof(RtFloat) * knotLength);
  if (!knot)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for knot");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < knotLength; i++)
  {  knot[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  /* get min[]  */
  if (Tcl_SplitList(interp, argv[4], &minLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[4]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  min = (RtFloat *)malloc(sizeof(RtFloat) * minLength);
  if (!min)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for min");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < minLength; i++)
  {  min[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  /* get max[]  */
  if (Tcl_SplitList(interp, argv[5], &maxLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[5]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  max = (RtFloat *)malloc(sizeof(RtFloat) * maxLength);
  if (!max)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for max");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < maxLength; i++)
  {  max[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  /* get n[]  */
  if (Tcl_SplitList(interp, argv[6], &nLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[6]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  n = (RtInt *)malloc(sizeof(RtInt) * nLength);
  if (!n)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for n");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < nLength; i++)
  {  n[i] = (RtInt)atoi(argv2[i]);
  }
  free(argv2);

  /* get u[]  */
  if (Tcl_SplitList(interp, argv[7], &uLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[7]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  u = (RtFloat *)malloc(sizeof(RtFloat) * uLength);
  if (!u)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for u");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < uLength; i++)
  {  u[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  /* get v[]  */
  if (Tcl_SplitList(interp, argv[8], &vLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[8]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  v = (RtFloat *)malloc(sizeof(RtFloat) * vLength);
  if (!v)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for v");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < vLength; i++)
  {  v[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);

  /* get w[]  */
  if (Tcl_SplitList(interp, argv[9], &wLength, &argv2) != TCL_OK)
  {  sprintf(errBuf, "%s : problem splitting <%s> as a list", argv[0], argv[9]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  w = (RtFloat *)malloc(sizeof(RtFloat) * wLength);
  if (!w)
  {  sprintf(errBuf, "RiTrimCurve : unable to malloc memory for w");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  for (i = 0; i < wLength; i++)
  {  w[i] = (RtFloat)atof(argv2[i]);
  }
  free(argv2);


  // RiTrimCurve(nLoops, nCurves, order, knot, min, max, n, u, v, w);
  // free(nCurves);
  // free(order);
  // free(knot);
  // free(min);
  // free(max);
  // free(n);
  // free(u);
  // free(v);
  // free(w);

  newRIBCommand = [[RIBTrimCurve alloc] init];
  [newRIBCommand setNLoops:nLoops nCurves:nCurves 
                    order:order len:orderLength
                    knot:knot len:knotLength 
                    min:min len:minLength 
                    max:max len:maxLength 
                    n2:n len:nLength 
                    u:u len:uLength 
                    v:v len:vLength 
                    w:w len:wLength];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_RiSphere(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "radius zMin zMax thetaMax [parameterlist]";
  int	num_args = 5, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiSphere : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiSphereV((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), (RtFloat)atof(argv[3]), (RtFloat)atof(argv[4]), n, tokens, parms);

  newRIBCommand = [[RIBSphere alloc] init];
  [newRIBCommand setRadius:(RtFloat)atof(argv[1]) zMin:(RtFloat)atof(argv[2]) zMax:(RtFloat)atof(argv[3]) thetaMax:(RtFloat)atof(argv[4])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiCone(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "height radius thetaMax [parameterlist]";
  int	num_args = 4, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiCone : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiConeV((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), (RtFloat)atof(argv[3]), n, tokens, parms);

  newRIBCommand = [[RIBCone alloc] init];
  [newRIBCommand setHeight:(RtFloat)atof(argv[1]) radius:(RtFloat)atof(argv[2]) thetaMax:(RtFloat)atof(argv[3])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiCylinder(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "radius zMin zMax thetaMax [parameterlist]";
  int	num_args = 5, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiCylinder : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiCylinderV((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), (RtFloat)atof(argv[3]), (RtFloat)atof(argv[4]), n, tokens, parms);

  newRIBCommand = [[RIBCylinder alloc] init];
  [newRIBCommand setRadius:(RtFloat)atof(argv[1]) zMin:(RtFloat)atof(argv[2]) zMax:(RtFloat)atof(argv[3]) thetaMax:(RtFloat)atof(argv[4])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiHyperboloid(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "x1 y1 z1 x2 y2 z2 thetaMax [parameterlist]"; // or "{x1 y1 z1} {x2 y2 z2} thetamax [parameterlist]"
  int	num_args = 8, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  RtPoint    point1, point2;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc < 8) && ((argc != 4) || (argc != 6)))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiHyperboloid : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  point1[0] = (RtFloat)atof(argv[1]);
  point1[1] = (RtFloat)atof(argv[2]);
  point1[2] = (RtFloat)atof(argv[3]);

  point2[0] = (RtFloat)atof(argv[4]);
  point2[1] = (RtFloat)atof(argv[5]);
  point2[2] = (RtFloat)atof(argv[6]);

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiHyperboloidV(point1, point2, (RtFloat)atof(argv[7]), n, tokens, parms);

  newRIBCommand = [[RIBHyperboloid alloc] init];
  [newRIBCommand setPoint1:point1 point2:point2 thetaMax:(RtFloat)atof(argv[7])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiParaboloid(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "rMax zMin zMax thetaMax [parameterlist]";
  int	num_args = 5, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ((argc+1) % 2)
  {  sprintf(errBuf, "RiParaboloid : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiParaboloidV((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), (RtFloat)atof(argv[3]), (RtFloat)atof(argv[4]), n, tokens, parms);

  newRIBCommand = [[RIBParaboloid alloc] init];
  [newRIBCommand setRMax:(RtFloat)atof(argv[1]) zMin:(RtFloat)atof(argv[2]) zMax:(RtFloat)atof(argv[3]) thetaMax:(RtFloat)atof(argv[4])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiDisk(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "height radius thetaMax [parameterlist]";
  int	num_args = 4, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiDisk : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiDiskV((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), (RtFloat)atof(argv[3]), n, tokens, parms);

  newRIBCommand = [[RIBDisk alloc] init];
  [newRIBCommand setHeight:(RtFloat)atof(argv[1]) radius:(RtFloat)atof(argv[2]) thetaMax:(RtFloat)atof(argv[3])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiTorus(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "majorRadius minorRadius phiMin phiMax thetaMax [parameterlist]";
  int	num_args = 6, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiTorus : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiTorus((RtFloat)atof(argv[1]), (RtFloat)atof(argv[2]), 
  //	  (RtFloat)atof(argv[3]), (RtFloat)atof(argv[4]), (RtFloat)atof(argv[5]), n, tokens, parms);

  newRIBCommand = [[RIBTorus alloc] init];
  [newRIBCommand setMajorRadius:(RtFloat)atof(argv[1]) minorRadius:(RtFloat)atof(argv[2]) 
                    phiMin:(RtFloat)atof(argv[3]) phiMax:(RtFloat)atof(argv[4]) thetaMax:(RtFloat)atof(argv[5])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}



static int
cmd_RiGeometry(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "type [parameterlist]";
  int	num_args = 2, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "RiGeometry : parameter list must be in groups of two, i.e. the number of args is an even number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  // RiGeometryV((RtToken)argv[1], n, tokens, parms);

  if (n)
  {  free(tokens); free(parms); free(archiveVector);
  }

  return TCL_OK;
}


#define MAX_LINE_LENGTH 1024

static int
cmd_RiArchiveRecord(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = " comment|structure stringWithNoNewlines";
  int	i, bytesLeft;
  id    newRIBCommand;
  static  char commentBuf[MAX_LINE_LENGTH + 1];

 
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc < 2)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  commentBuf[0] = '\0';
  bytesLeft = MAX_LINE_LENGTH;
  for (i = 2; i < argc; i++)
  {  strncat(commentBuf, argv[i], bytesLeft);
     bytesLeft -= strlen(argv[i]);
     strncat(commentBuf, " ", bytesLeft);
     bytesLeft--;
  }
  if (!strcmp(argv[1], "comment"))
  {  // RiArchiveRecord("comment", "%s", argv[2]);
     newRIBCommand = [[RIBArchiveRecord alloc] init];
     [newRIBCommand setType:"comment" format:commentBuf];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }
  if (!strcmp(argv[1], "structure"))
  {  // RiArchiveRecord("structure", "%s", argv[2]);
     newRIBCommand = [[RIBArchiveRecord alloc] init];
     [newRIBCommand setType:"structure" format:commentBuf];
     [newRIBCommand setMyShape:[me currentShape]];
     if ([me evaluatingEveCommand])
     {  [me setTmpRIBCommand:newRIBCommand];
     }
     else
     {  [[me currentShape] appendRIBCommand:newRIBCommand];
     }
     return TCL_OK;
  }
  sprintf(errBuf, 
	  "RiArchiveRecord : first arg must be one of: comment or structure");
  Tcl_AppendResult(interp, errBuf, (char *)NULL);
  return TCL_ERROR;
}



// EveCmd {wwSet foo $bar}
static int
cmd_WWSet(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "varName varValue";
  id    newRIBCommand;

 
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != 3)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  // okay, set this in the current context
  if (![[me tclInterp] setVar:argv[1] toValue:argv[2]])
  {  sprintf(errBuf, "%s: unable to set %s to %s", argv[0], argv[1], argv[2]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  //okay, that worked, so now we need to malloc up a new WWSet object to store this state
  newRIBCommand = [[WWSet alloc] initWithInterp:[me tclInterp]];
  [newRIBCommand setVar:argv[1] value:argv[2]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }
  return TCL_OK;
}


static int
cmd_EveCmd(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "eveCommand [{{sampleTime0 { {sampleComponentAGeneratorName weight.a sample0.a} ... {sampleComponentNGeneratorName weight.n sample0.n}}} {sampleTime1  {sampleComponent1AGeneratorName weight.a sample1.a} ... {sampleComponent0NGeneratorName weight.n sample1.n} }}]", *retBuf;
  int	ret;
  id    newRIBCommand;

 
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ((argc != 2) && (argc != 3))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me evaluatingEveProc])
  {  sprintf(errBuf, "you cannot nest an EveCmd call inside an EveProc call");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[EveCommand alloc] initWithInterp:[me tclInterp] 
                                      eveParser:(id)me 
                                      shape:[me currentShape] 
                                      cmd:argv[1] 
                                      clock:[me sceneClock] 
                                      frozen:[me frozen]];
  if (!newRIBCommand) // evalutation of this rib command failed. we
  {                   // need to get the error code, though, so we 
                      // reevaluate the command to get it...
     retBuf = [[me tclInterp] eval:argv[1] :&ret];
     sprintf(errBuf, "unable to build new RIBCommand from <%s> inside EveCmd due to <%s>", argv[1], retBuf);
     NXLogError(errBuf);
     NXLogError("\n");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     if (retBuf) {  free(retBuf); }
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (![newRIBCommand evalAndAddAsSamples:argv[2]])
     {  sprintf(errBuf, "difficulty parsing %s samples (check console for more errors)", argv[0]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        [newRIBCommand free];  
        return TCL_ERROR;
     }
  }

  // if we don't have a currentShape, that means we're in the limbo of
  // having blown away our old root shape but not having evaluated the
  // first AttributeBegin.  To fix this, we'll instantiate a new shape...

  if (![me currentShape])
  {  id newShape  = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]]; 
     [me setRiBegun:YES];
     [newShape setShapeName:"dummyShapeToHoldAnimatableCommands"];
     [me setTmpRootShape:newShape];
     [me setCurrentShape:newShape];
  } 
  [[me currentShape] appendRIBCommand:newRIBCommand];

  return TCL_OK;
}


static int
cmd_EveProc(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "eveProc [{{sampleTime0 {sample0}} {sampleTime1 {sample1}} ... {sampleTimeN {sampleN}}}]", *retBuf;
  int	ret;
  id    newRIBCommand;

  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if ((argc != 2) && (argc != 3))
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if ([me evaluatingEveProc])
  {  sprintf(errBuf, "you cannot nest EveProc calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  [me setEvaluatingEveProc:YES];
  newRIBCommand = [[EveProc alloc] initWithInterp:[me tclInterp] 
                                   eveParser:(id)me 
                                   shape:[me currentShape] 
                                   cmd:argv[1] 
                                   clock:[me sceneClock] frozen:[me frozen]];
  [me setEvaluatingEveProc:NO];

  if (!newRIBCommand) // evalutation of this rib command failed. we
  {                   // need to get the error code, though, so we 
                      // reevaluate the command to get it...
     retBuf = [[me tclInterp] eval:argv[1] :&ret];
     sprintf(errBuf, "unable to build new RIBCommand from <%s> inside EveProc due to <%s>", argv[1], retBuf);
     NXLogError(errBuf);
     NXLogError("\n");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     if (retBuf) {  free(retBuf); }
     return TCL_ERROR;
  }

  if (argc == 3)
  {  if (![newRIBCommand evalAndAddAsSamples:argv[2]])
     {  sprintf(errBuf, "difficulty parsing %s samples (check console for more errors)", argv[0]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        [newRIBCommand free];  
        return TCL_ERROR;
     }
  }

  // if we don't have a currentShape, that means we're in the limbo of
  // having blown away our old root shape but not having evaluated the
  // first AttributeBegin.  To fix this, we'll instantiate a new shape...

  if (![me currentShape])
  {  id newShape  = [[WW3DShape alloc] initWithInterp:[me tclInterp] andSceneClock:[me sceneClock]]; 
     [me setRiBegun:YES];
     [newShape setShapeName:"dummyShapeToHoldAnimatableCommands"];
     [me setTmpRootShape:newShape];
     [me setCurrentShape:newShape];
  } 
  [[me currentShape] appendRIBCommand:newRIBCommand];

  return TCL_OK;
}


static int
cmd_ApplyToCTM(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "eveCommand";
  int	num_args = 2, retVal;
  BOOL  oldFlag;

 
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  oldFlag = [me firmTransforms];
  [me setFirmTransforms:YES];
  retVal = [[me tclInterp] eval:argv[1]];
  [me setFirmTransforms:oldFlag];

  return retVal;
}


static int
cmd_updateView(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  [me updateView];
  return TCL_OK;
}


static int
cmd_synchWithScene(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  int   i, howMany = [me sceneIncr];
  char  ticksPassed[32];
  id    sceneClock = [me sceneClock];


  sprintf(errBuf, "evaluating %s...", argv[0]);

  // in the real WavesWorld system, this msg would be going from a
  // skill agent out to the shared state space of the dude.  It would hang
  // the skill agent until the next tick of the scene clock had passed.  In
  // a real-time system, this would be some amount of wall time, while in
  // the non-realtime version, it would be after either all non-amputated
  // executing skill agents had sent this msg for the given tick.
  // In this "dude builder" version, since the activity is single-threaded,
  // this just increments the scene clock and returns immediately.

  // actually, let's make this a little better.  There will be a global 
  // variable, scene(
  for (i = 0; i < howMany; i++)
  {  [sceneClock increment:nil];
  }
  // for now, we should probably also update the view...
  [me synchViewWithSceneClock];
  //[me updateView];

  // in the general case, we return the number of ticks that have
  // passed in the scene since the scene clock last received a synch msg
  // from this agent.  In this (somewhat degenerate) case, it will always
  // be one.  This, in conjunction with the read-only variable "ticksPerSecond",
  // allows an agent to keep in synch via dead-reckoning...

  sprintf(ticksPassed, "%d", howMany);
  Tcl_AppendResult(interp, ticksPassed, (char *)NULL);

  return TCL_OK;
}

static int
cmd_synchWithSceneInvisibly(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  int   i, howMany = [me sceneIncr];
  char  ticksPassed[32];
  id    sceneClock = [me sceneClock];


  sprintf(errBuf, "evaluating %s...", argv[0]);

  // in the real WavesWorld system, this msg would be going from a
  // skill agent out to the shared state space of the dude.  It would hang
  // the skill agent until the next tick of the scene clock had passed.  In
  // a real-time system, this would be some amount of wall time, while in
  // the non-realtime version, it would be after either all non-amputated
  // executing skill agents had sent this msg for the given tick.
  // In this "dude builder" version, since the activity is single-threaded,
  // this just increments the scene clock and returns immediately.

  // actually, let's make this a little better.  There will be a global 
  // variable, scene(
  for (i = 0; i < howMany; i++)
  {  [sceneClock increment:nil];
  }

  // in the general case, we return the number of ticks that have
  // passed in the scene since the scene clock last received a synch msg
  // from this agent.  In this (somewhat degenerate) case, it will always
  // be one.  This, in conjunction with the read-only variable "ticksPerSecond",
  // allows an agent to keep in synch via dead-reckoning...

  sprintf(ticksPassed, "%d", howMany);
  Tcl_AppendResult(interp, ticksPassed, (char *)NULL);

  return TCL_OK;
}

static int
cmd_camera(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char  *my_args = "codeToGiveToCameraInterp";
  int	num_args = 2;
  char  *retString = NULL;
  int   ret;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  retString = [[[me camera] tclInterp] eval:argv[1] :&ret];
  if (retString)
  {  Tcl_AppendResult(interp, retString, (char *)NULL);
     free(retString);
  }
  return ret;
}


static int
cmd_TreatAttributeBeginLikeStartShape(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char  *my_args = "[newValue]";
  int	newValue, num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 1) // just return the current value 
  {  sprintf(errBuf, "%d", [me treatAttributeBeginLikeStartShape]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }
  else
  {  if (Tcl_GetBoolean(interp, argv[1], &newValue) != TCL_OK)
     {  sprintf(errBuf, "%s isn't a valid boolean value", argv[1]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     [me setTreatAttributeBeginLikeStartShape:(BOOL)newValue];
     sprintf(errBuf, "%d", [me treatAttributeBeginLikeStartShape]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }

  return TCL_OK;
}


static int
cmd_TreatTransformBeginLikeAttributeBegin(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char  *my_args = "[newValue]";
  int	newValue, num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 1) // just return the current value 
  {  sprintf(errBuf, "%d", [me treatTransformBeginLikeAttributeBegin]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }
  else
  {  if (Tcl_GetBoolean(interp, argv[1], &newValue) != TCL_OK)
     {  sprintf(errBuf, "%s isn't a valid boolean value", argv[1]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     [me setTreatTransformBeginLikeAttributeBegin:(BOOL)newValue];
     sprintf(errBuf, "%d", [me treatTransformBeginLikeAttributeBegin]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }

  return TCL_OK;
}


static int
cmd_ApplyShadersDirectlyToCurrentShape(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char  *my_args = "[newValue]";
  int	newValue, num_args = 2;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc > num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc == 1) // just return the current value 
  {  sprintf(errBuf, "%d", [me applyShadersDirectlyToCurrentShape]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }
  else
  {  if (Tcl_GetBoolean(interp, argv[1], &newValue) != TCL_OK)
     {  sprintf(errBuf, "%s isn't a valid boolean value", argv[1]);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     }
     [me setApplyShadersDirectlyToCurrentShape:(BOOL)newValue];
     sprintf(errBuf, "%d", [me applyShadersDirectlyToCurrentShape]);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
  }

  return TCL_OK;
}


static int
cmd_WW3DText(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
/*
 * WW3DText fontName fontSize theText
 */
{
  const 
      char  *cmdUsage = "fontName fontSize theText [left|center|right]";
  int       expectedCmdArgs = 4;
  double    fontSize;
  Font      *theFont;
  id        newRIBCommand;
  int       justification = NX_CENTERED;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf];
  [[me statusText] display];
  NXPing();
  if (![me riBegun]) 
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc < expectedCmdArgs)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], cmdUsage);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (Tcl_GetDouble(interp, argv[2], &fontSize) != TCL_OK) 
  {  sprintf(errBuf, "USAGE: %s %s (second arg must be a floating point number)", argv[0], cmdUsage);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  if (argc == (expectedCmdArgs + 1))
  {  if (strcmp(argv[expectedCmdArgs], "left") && strcmp(argv[expectedCmdArgs], "center") && strcmp(argv[expectedCmdArgs], "right"))
     {  sprintf(errBuf, "USAGE: %s %s (final arg must be left, center, or right)", argv[0], cmdUsage);
        Tcl_AppendResult(interp, errBuf, (char *)NULL);
        return TCL_ERROR;
     } 
     if (!strcmp(argv[expectedCmdArgs], "left"))
     {  justification = NX_LEFTALIGNED;
     }
     else
     {  if (!strcmp(argv[expectedCmdArgs], "center"))
        {  justification = NX_CENTERED;
        }
        else
        {  justification = NX_RIGHTALIGNED;
        } 
     }
  }

  theFont = [Font newFont:argv[1] size:(float)fontSize];
  if (!theFont) 
  {  sprintf(errBuf, "Unable to instantiate a Font with a font name of %s and size %f", argv[1], (float)fontSize);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  newRIBCommand = [[WW3DText alloc] initWithCharPath:argv[3] usingFont:theFont myShape:[me currentShape] justification:justification];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_WW3DSquishySphere(me, interp, argc, argv)
WWEveParser    *me;
Tcl_Interp     *interp;
int            argc;
char           **argv;
{
  char  *my_args = "radius zMin zMax thetaMax yScale [parameterlist]";
  int	num_args = 6, n;
  RtToken    *tokens = (RtToken *)RI_NULL;
  RtPointer  *parms = (RtPointer *)RI_NULL;
  int        *nVector = NULL, 
             *typeVector = NULL;
  char       **archiveVector = NULL;
  id         newRIBCommand;


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (![me riBegun])
  {  sprintf(errBuf, "You must call RiBegin before making any RIB calls");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc < num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (argc % 2)
  {  sprintf(errBuf, "WW3DSquishySphere : parameter list must be in groups of two, i.e. the number of args is an odd number");
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  n = 0;
  if (argc > num_args)
  {  n = (argc - num_args) / 2;
     if (!buildParameterList(me, interp, n, &tokens, &parms, &archiveVector, &nVector, &typeVector, num_args, argv))
     {  return TCL_ERROR;
     }
  }

  newRIBCommand = [[WW3DSquishySphere alloc] init];
  [newRIBCommand setRadius:(RtFloat)atof(argv[1]) zMin:(RtFloat)atof(argv[2]) zMax:(RtFloat)atof(argv[3]) thetaMax:(RtFloat)atof(argv[4])
                    yScale:(RtFloat)atof(argv[5])
                    n:n tokens:tokens parms:parms archiveVector:archiveVector printfTypeVector:typeVector printfNVector:nVector];
  [newRIBCommand setMyShape:[me currentShape]];
  if ([me evaluatingEveCommand])
  {  [me setTmpRIBCommand:newRIBCommand];
  }
  else
  {  [[me currentShape] appendRIBCommand:newRIBCommand];
  }

  return TCL_OK;
}


static int
cmd_defineClass(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char  *my_args = "newClassName instanceVariables executableCode";
  int	num_args = 4;
  extern  int Tcl_ProcCmd();


  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();

  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  return Tcl_ProcCmd(me, interp, argc, argv);
}

static int
cmd_articulatedVariableChangesAs(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  char    *my_args = "variableName startTime endTime uBasedCommand";
  int	  num_args = 5;
  double  foo;
  float   startTime, endTime;
  id      newVarBehavior;

 
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  if (argc != num_args)
  {  sprintf(errBuf, "USAGE: %s %s", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }

  if (Tcl_GetDouble(interp, argv[2], &foo) != TCL_OK) 
  {  sprintf(errBuf, "USAGE: %s %s (second arg must be a floating point number)", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  startTime = (float)foo;

  if (Tcl_GetDouble(interp, argv[3], &foo) != TCL_OK) 
  {  sprintf(errBuf, "USAGE: %s %s (third arg must be a floating point number)", argv[0], my_args);
     Tcl_AppendResult(interp, errBuf, (char *)NULL);
     return TCL_ERROR;
  }
  endTime = (float)foo;

  newVarBehavior = [[WWArticulatedVariableBehavior alloc] initWithInterp:[me tclInterp] 
                                                          startTime:(float)startTime
                                                          endTime:(float)endTime 
                                                          var:(const char *)argv[1]
                                                          expression:(const char *)argv[4]];
  [me addArticulatedVariableBehavior:newVarBehavior];

  return TCL_OK;
}

static int
cmd_noop(me, interp, argc, argv)
WWEveParser *me;
Tcl_Interp *interp;
int argc;
char **argv;
{
  sprintf(errBuf, "evaluating %s...", argv[0]);
  [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing();
  return TCL_OK;
}

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////// methods /////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

- (int)sceneIncr { return sceneIncr; }

- setSceneIncr:(int)newSceneIncr
{
  char   buf[128];


  sceneIncr = newSceneIncr;
  sprintf(buf, "%d", sceneIncr);
  //[tclInterp setVar2:"scene" :"incr" toReadOnlyValue:buf];
  [tclInterp setVar2:"scene" :"incr" toValue:buf];

  return self;
}


// someone is writing a new value for the scene(incr) parameter, so we need
// to update the WWEveParser to reflect that new value...
char *WriteProcForSceneIncr(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags)
{
  char   *varString;
  int   sceneIncr = 1;


  varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2];
  sscanf(varString, "%d", &sceneIncr);
  [[(WWTCLVarTrace *)clientData datum] setSceneIncr:sceneIncr];

  return NULL;
}


// someone is reading a value for the scene(incr) parameter, so we need
// to " read-through" the WW3DCamera to reflect the current value...
char *ReadProcForSceneIncr(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags)
{
  char  buf[128];
  int   sceneIncr;


  sceneIncr = [[(WWTCLVarTrace *)clientData datum] sceneIncr];
  sprintf(buf, "%d", sceneIncr);
  //[[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toReadOnlyValue:buf];
  [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf];

  return NULL;
}



- initWWEveParser
{
  char         *valAsString, *varName;


  valAsString = (char *)NXZoneCalloc([self zone], 256, sizeof(char));
  varName = (char *)NXZoneCalloc([self zone], 256, sizeof(char));

  // you may be asking yourself here: "why is wave, that bozo, copying
  // the strings that correspond to the variables names into a tmp
  // variable?  Is he really that wasteful, just because he has bigger
  // and more expensive equipment than I do?  Is he intentionally wasting
  // my precious time?"  Well, sports fans, no.  The problem is that
  // the current (7.3) implementation of tcl still uses a performance
  // hack that gets bit by compilers being smart.  The short answer is
  // if you hand tcl a const char* that the compiler has squirreled away
  // somewhere in read-only space, you will dump core, because tcl,
  // while doing a comparison on array elements, attempts to stick a '\0'
  // where the '(' is so it can do a fast hash table lookup.  It's very
  // good about taking the '\0' out once its done, but unfortunately, 
  // you'll never get the chance...  This is reasonably well documented
  // in the tcl doc, and given the efficiency, I can't really complain,
  // but it *is* a bug (whether in C, the compiler, or tcl, you make the call).
  // Anyway, to get around it, you either use the setVar2 version, or
  // you make sure that the string you hand into setVar is writable.
  // gak...

  // 
  strcpy(varName, "scene(incr)");
  sprintf(valAsString, "%d", [self sceneIncr]); // turn the value into its tcl equivalent
  //[tclInterp setVar:varName toReadOnlyValue:valAsString]; // don't do this as it sets up a write trace we don't need
  [tclInterp setVar:varName toValue:valAsString];
  [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForSceneIncr usingData:(ClientData)self];
  [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForSceneIncr usingData:(ClientData)self];

  // RIB bindings
  [tclInterp addCommand:"version" :cmd_noop :self];
  [tclInterp addCommand:"render" :cmd_render :self];
  [tclInterp addCommand:"massageRIB" :cmd_massageRIB :self];

  [tclInterp addCommand:"Declare" :cmd_RiDeclare :self];
  [tclInterp addCommand:"Begin" :cmd_RiBegin :self];
  [tclInterp addCommand:"End" :cmd_RiEnd :self];
  [tclInterp addCommand:"FrameBegin" :cmd_noop :self];
  [tclInterp addCommand:"FrameEnd" :cmd_noop :self];
  [tclInterp addCommand:"WorldBegin" :cmd_RiWorldBegin :self];
  [tclInterp addCommand:"WorldEnd" :cmd_RiWorldEnd :self];
  [tclInterp addCommand:"Format" :cmd_noop :self];
  [tclInterp addCommand:"FrameAspectRatio" :cmd_noop :self];
  [tclInterp addCommand:"ScreenWindow" :cmd_noop :self];
  [tclInterp addCommand:"CropWindow" :cmd_noop :self];
  [tclInterp addCommand:"Clipping" :cmd_noop :self];
  [tclInterp addCommand:"DepthOfField" :cmd_noop :self];
  [tclInterp addCommand:"Shutter" :cmd_noop :self];
  [tclInterp addCommand:"PixelVariance" :cmd_noop :self];
  [tclInterp addCommand:"PixelSamples" :cmd_noop :self];
  [tclInterp addCommand:"PixelFilter" :cmd_noop :self];
  [tclInterp addCommand:"Exposure" :cmd_noop :self];
  [tclInterp addCommand:"Quantize" :cmd_noop :self];
  [tclInterp addCommand:"ColorSamples" :cmd_RiColorSamples :self];
  [tclInterp addCommand:"RelativeDetail" :cmd_noop :self];
  [tclInterp addCommand:"AttributeBegin" :cmd_RiAttributeBegin :self];
  [tclInterp addCommand:"AttributeEnd" :cmd_RiAttributeEnd :self];
  [tclInterp addCommand:"Color" :cmd_RiColor :self];
  [tclInterp addCommand:"Opacity" :cmd_RiOpacity :self];
  [tclInterp addCommand:"TextureCoordinates" :cmd_RiTextureCoordinates :self];
  [tclInterp addCommand:"Illuminate" :cmd_RiIlluminate :self];
  [tclInterp addCommand:"ShadingRate" :cmd_RiShadingRate :self];
  [tclInterp addCommand:"ShadingInterpolation" :cmd_RiShadingInterpolation :self];
  [tclInterp addCommand:"Matte" :cmd_RiMatte :self];
  [tclInterp addCommand:"Bound" :cmd_RiBound :self];
  [tclInterp addCommand:"Detail" :cmd_noop :self];
  [tclInterp addCommand:"DetailRange" :cmd_noop :self];
  [tclInterp addCommand:"GeometricApproximation" :cmd_RiGeometricApproximation :self];
  [tclInterp addCommand:"Orientation" :cmd_RiOrientation :self];
  [tclInterp addCommand:"ReverseOrientation" :cmd_RiReverseOrientation :self];
  [tclInterp addCommand:"Sides" :cmd_RiSides :self];
  [tclInterp addCommand:"Identity" :cmd_RiIdentity :self];
  [tclInterp addCommand:"Transform" :cmd_RiTransform :self];
  [tclInterp addCommand:"ConcatTransform" :cmd_RiConcatTransform :self];
  [tclInterp addCommand:"Perspective" :cmd_RiPerspective :self];
  [tclInterp addCommand:"Translate" :cmd_RiTranslate :self];
  [tclInterp addCommand:"Rotate" :cmd_RiRotate :self];
  [tclInterp addCommand:"Scale" :cmd_RiScale :self];
  [tclInterp addCommand:"Skew" :cmd_RiSkew :self];
  [tclInterp addCommand:"CoordinateSystem" :cmd_RiCoordinateSystem :self];
  [tclInterp addCommand:"TransformPoints" :cmd_noop :self];
  [tclInterp addCommand:"TransformBegin" :cmd_RiTransformBegin :self];
  [tclInterp addCommand:"TransformEnd" :cmd_RiTransformEnd :self];
  [tclInterp addCommand:"Attribute" :cmd_RiAttribute :self];
  [tclInterp addCommand:"SolidBegin" :cmd_RiSolidBegin :self];
  [tclInterp addCommand:"SolidEnd" :cmd_RiSolidEnd :self];
  [tclInterp addCommand:"ObjectBegin" :cmd_RiObjectBegin :self];
  [tclInterp addCommand:"ObjectEnd" :cmd_RiObjectEnd :self];
  [tclInterp addCommand:"ObjectInstance" :cmd_RiObjectInstance :self];
  [tclInterp addCommand:"MotionBegin" :cmd_RiMotionBegin :self];
  [tclInterp addCommand:"MotionEnd" :cmd_RiMotionEnd :self];
  [tclInterp addCommand:"Projection" :cmd_noop :self];
  [tclInterp addCommand:"Imager" :cmd_RiImager :self];
  [tclInterp addCommand:"Display" :cmd_noop :self];
  [tclInterp addCommand:"Hider" :cmd_RiHider :self];
  [tclInterp addCommand:"LightSource" :cmd_RiLightSource :self];
  [tclInterp addCommand:"AreaLightSource" :cmd_RiAreaLightSource :self];
  [tclInterp addCommand:"Surface" :cmd_RiSurface :self];
  [tclInterp addCommand:"Atmosphere" :cmd_RiAtmosphere :self];
  [tclInterp addCommand:"Interior" :cmd_RiInterior :self];
  [tclInterp addCommand:"Exterior" :cmd_RiExterior :self];
  [tclInterp addCommand:"Deformation" :cmd_RiDeformation :self];
  [tclInterp addCommand:"Displacement" :cmd_RiDisplacement :self];
  [tclInterp addCommand:"Polygon" :cmd_RiPolygon :self];
  [tclInterp addCommand:"GeneralPolygon" :cmd_RiGeneralPolygon :self];
  [tclInterp addCommand:"PointsPolygons" :cmd_RiPointsPolygons :self];
  [tclInterp addCommand:"PointsGeneralPolygons" :cmd_RiPointsGeneralPolygons :self];
  [tclInterp addCommand:"Basis" :cmd_RiBasis :self];
  [tclInterp addCommand:"Patch" :cmd_RiPatch :self];
  [tclInterp addCommand:"PatchMesh" :cmd_RiPatchMesh :self];
  [tclInterp addCommand:"NuPatch" :cmd_RiNuPatch :self];
  [tclInterp addCommand:"Sphere" :cmd_RiSphere :self];
  [tclInterp addCommand:"Cone" :cmd_RiCone :self];
  [tclInterp addCommand:"Cylinder" :cmd_RiCylinder :self];
  [tclInterp addCommand:"Hyperboloid" :cmd_RiHyperboloid :self];
  [tclInterp addCommand:"Paraboloid" :cmd_RiParaboloid :self];
  [tclInterp addCommand:"Disk" :cmd_RiDisk :self];
  [tclInterp addCommand:"Torus" :cmd_RiTorus :self];

  [tclInterp addCommand:"TrimCurve" :cmd_RiTrimCurve :self];
  [tclInterp addCommand:"Geometry" :cmd_RiGeometry :self];
  [tclInterp addCommand:"GeometricRepresentation" :cmd_noop :self];
  [tclInterp addCommand:"Option" :cmd_RiOption :self];

  [tclInterp addCommand:"MakeTexture" :cmd_RiMakeTexture :self];
  [tclInterp addCommand:"MakeBump" :cmd_noop :self];
  [tclInterp addCommand:"MakeLatLongEnvironment" :cmd_noop :self];
  [tclInterp addCommand:"MakeCubeFaceEnvironment" :cmd_noop :self];
  [tclInterp addCommand:"MakeShadow" :cmd_noop :self];
  [tclInterp addCommand:"ErrorHandler" :cmd_noop :self];
  [tclInterp addCommand:"ArchiveRecord" :cmd_RiArchiveRecord :self];

  // Ri bindings, i.e. like the C bindings
  [tclInterp addCommand:"RiDeclare" :cmd_RiDeclare :self];
  [tclInterp addCommand:"RiBegin" :cmd_RiBegin :self];
  [tclInterp addCommand:"RiEnd" :cmd_RiEnd :self];
  [tclInterp addCommand:"RiFrameBegin" :cmd_noop :self];
  [tclInterp addCommand:"RiFrameEnd" :cmd_noop :self];
  [tclInterp addCommand:"RiWorldBegin" :cmd_RiWorldBegin :self];
  [tclInterp addCommand:"RiWorldEnd" :cmd_RiWorldEnd :self];
  [tclInterp addCommand:"RiFormat" :cmd_noop :self];
  [tclInterp addCommand:"RiFrameAspectRatio" :cmd_noop :self];
  [tclInterp addCommand:"RiScreenWindow" :cmd_noop :self];
  [tclInterp addCommand:"RiCropWindow" :cmd_noop :self];
  [tclInterp addCommand:"RiClipping" :cmd_noop :self];
  [tclInterp addCommand:"RiDepthOfField" :cmd_noop :self];
  [tclInterp addCommand:"RiShutter" :cmd_noop :self];
  [tclInterp addCommand:"RiPixelVariance" :cmd_noop :self];
  [tclInterp addCommand:"RiPixelSamples" :cmd_noop :self];
  [tclInterp addCommand:"RiPixelFilter" :cmd_noop :self];
  [tclInterp addCommand:"RiExposure" :cmd_noop :self];
  [tclInterp addCommand:"RiQuantize" :cmd_noop :self];
  [tclInterp addCommand:"RiColorSamples" :cmd_RiColorSamples :self];
  [tclInterp addCommand:"RiRelativeDetail" :cmd_noop :self];
  [tclInterp addCommand:"RiAttributeBegin" :cmd_RiAttributeBegin :self];
  [tclInterp addCommand:"RiAttributeEnd" :cmd_RiAttributeEnd :self];
  [tclInterp addCommand:"RiColor" :cmd_RiColor :self];
  [tclInterp addCommand:"RiOpacity" :cmd_RiOpacity :self];
  [tclInterp addCommand:"RiTextureCoordinates" :cmd_RiTextureCoordinates :self];
  [tclInterp addCommand:"RiIlluminate" :cmd_RiIlluminate :self];
  [tclInterp addCommand:"RiShadingRate" :cmd_RiShadingRate :self];
  [tclInterp addCommand:"RiShadingInterpolation" :cmd_RiShadingInterpolation :self];
  [tclInterp addCommand:"RiMatte" :cmd_RiMatte :self];
  [tclInterp addCommand:"RiBound" :cmd_RiBound :self];
  [tclInterp addCommand:"RiDetail" :cmd_noop :self];
  [tclInterp addCommand:"RiDetailRange" :cmd_noop :self];
  [tclInterp addCommand:"RiGeometricApproximation" :cmd_RiGeometricApproximation :self];
  [tclInterp addCommand:"RiOrientation" :cmd_RiOrientation :self];
  [tclInterp addCommand:"RiReverseOrientation" :cmd_RiReverseOrientation :self];
  [tclInterp addCommand:"RiSides" :cmd_RiSides :self];
  [tclInterp addCommand:"RiIdentity" :cmd_RiIdentity :self];
  [tclInterp addCommand:"RiTransform" :cmd_RiTransform :self];
  [tclInterp addCommand:"RiConcatTransform" :cmd_RiConcatTransform :self];
  [tclInterp addCommand:"RiPerspective" :cmd_RiPerspective :self];
  [tclInterp addCommand:"RiTranslate" :cmd_RiTranslate :self];
  [tclInterp addCommand:"RiRotate" :cmd_RiRotate :self];
  [tclInterp addCommand:"RiScale" :cmd_RiScale :self];
  [tclInterp addCommand:"RiSkew" :cmd_noop :self];
  [tclInterp addCommand:"RiCoordinateSystem" :cmd_RiCoordinateSystem :self];
  [tclInterp addCommand:"RiTransformPoints" :cmd_noop :self];
  [tclInterp addCommand:"RiTransformBegin" :cmd_RiTransformBegin :self];
  [tclInterp addCommand:"RiTransformEnd" :cmd_RiTransformEnd :self];
  [tclInterp addCommand:"RiAttribute" :cmd_RiAttribute :self];
  [tclInterp addCommand:"RiSolidBegin" :cmd_RiSolidBegin :self];
  [tclInterp addCommand:"RiSolidEnd" :cmd_RiSolidEnd :self];
  [tclInterp addCommand:"RiObjectBegin" :cmd_RiObjectBegin :self];
  [tclInterp addCommand:"RiObjectEnd" :cmd_RiObjectEnd :self];
  [tclInterp addCommand:"RiObjectInstance" :cmd_RiObjectInstance :self];
  [tclInterp addCommand:"RiMotionBegin" :cmd_noop :self];
  [tclInterp addCommand:"RiMotionEnd" :cmd_noop :self];
  [tclInterp addCommand:"RiProjection" :cmd_noop :self];
  [tclInterp addCommand:"RiImager" :cmd_RiImager :self];
  [tclInterp addCommand:"RiDisplay" :cmd_noop :self];
  [tclInterp addCommand:"RiHider" :cmd_RiHider :self];
  [tclInterp addCommand:"RiLightSource" :cmd_RiLightSource :self];
  [tclInterp addCommand:"RiAreaLightSource" :cmd_RiAreaLightSource :self];
  [tclInterp addCommand:"RiSurface" :cmd_RiSurface :self];
  [tclInterp addCommand:"RiAtmosphere" :cmd_RiAtmosphere :self];
  [tclInterp addCommand:"RiInterior" :cmd_RiInterior :self];
  [tclInterp addCommand:"RiExterior" :cmd_RiExterior :self];
  [tclInterp addCommand:"RiDeformation" :cmd_RiDeformation :self];
  [tclInterp addCommand:"RiDisplacement" :cmd_RiDisplacement :self];
  [tclInterp addCommand:"RiPolygon" :cmd_RiPolygon :self];
  [tclInterp addCommand:"RiGeneralPolygon" :cmd_RiGeneralPolygon :self];
  [tclInterp addCommand:"RiPointsPolygons" :cmd_RiPointsPolygons :self];
  [tclInterp addCommand:"RiPointsGeneralPolygons" :cmd_RiPointsGeneralPolygons :self];
  [tclInterp addCommand:"RiBasis" :cmd_RiBasis :self];
  [tclInterp addCommand:"RiPatch" :cmd_RiPatch :self];
  [tclInterp addCommand:"RiPatchMesh" :cmd_RiPatchMesh :self];
  [tclInterp addCommand:"RiNuPatch" :cmd_RiNuPatch :self];
  [tclInterp addCommand:"RiSphere" :cmd_RiSphere :self];
  [tclInterp addCommand:"RiCone" :cmd_RiCone :self];
  [tclInterp addCommand:"RiCylinder" :cmd_RiCylinder :self];
  [tclInterp addCommand:"RiHyperboloid" :cmd_RiHyperboloid :self];
  [tclInterp addCommand:"RiParaboloid" :cmd_RiParaboloid :self];
  [tclInterp addCommand:"RiDisk" :cmd_RiDisk :self];
  [tclInterp addCommand:"RiTorus" :cmd_RiTorus :self];

  [tclInterp addCommand:"RiTrimCurve" :cmd_RiTrimCurve :self];
  [tclInterp addCommand:"RiGeometry" :cmd_RiGeometry :self];
  [tclInterp addCommand:"RiGeometricRepresentation" :cmd_noop :self];
  [tclInterp addCommand:"RiOption" :cmd_RiOption :self];

  [tclInterp addCommand:"RiMakeTexture" :cmd_RiMakeTexture :self];
  [tclInterp addCommand:"RiMakeBump" :cmd_noop :self];
  [tclInterp addCommand:"RiMakeLatLongEnvironment" :cmd_noop :self];
  [tclInterp addCommand:"RiMakeCubeFaceEnvironment" :cmd_noop :self];
  [tclInterp addCommand:"RiMakeShadow" :cmd_noop :self];
  [tclInterp addCommand:"RiErrorHandler" :cmd_noop :self];
  [tclInterp addCommand:"RiArchiveRecord" :cmd_RiArchiveRecord :self];

  // because MacroModel is still lame, I have these bindings...
  [tclInterp addCommand:"surface" :cmd_RiSurface :self];
  [tclInterp addCommand:"color" :cmd_RiColor :self];
  [tclInterp addCommand:"opacity" :cmd_RiOpacity :self];

  //new, weird eve commands...
  [tclInterp addCommand:"articulatedVariableChangesAs" :cmd_articulatedVariableChangesAs :self];
  [tclInterp addCommand:"aVariableChangesAs" :cmd_articulatedVariableChangesAs :self];

  [tclInterp addCommand:"defineClass:" :cmd_defineClass :self];

  [tclInterp addCommand:"Mutable" :cmd_EveProc :self];
  [tclInterp addCommand:"Mutable:" :cmd_EveProc :self];
  [tclInterp addCommand:"mutable" :cmd_EveProc :self];
  [tclInterp addCommand:"mutable:" :cmd_EveProc :self];

  [tclInterp addCommand:"Animatable" :cmd_EveProc :self];
  [tclInterp addCommand:"Animatable:" :cmd_EveProc :self];
  [tclInterp addCommand:"animatable" :cmd_EveProc :self];
  [tclInterp addCommand:"animatable:" :cmd_EveProc :self];

  [tclInterp addCommand:"EveCmd" :cmd_EveCmd :self];
  [tclInterp addCommand:"eveCmd" :cmd_EveCmd :self];
  [tclInterp addCommand:"aCmd" :cmd_EveCmd :self];
  [tclInterp addCommand:"ACmd" :cmd_EveCmd :self];
  [tclInterp addCommand:"articulatedCmd" :cmd_EveCmd :self];
  [tclInterp addCommand:"ArticulatedCmd" :cmd_EveCmd :self];

  [tclInterp addCommand:"EveProc" :cmd_EveProc :self];
  [tclInterp addCommand:"eveProc" :cmd_EveProc :self];
  [tclInterp addCommand:"aProc" :cmd_EveProc :self];
  [tclInterp addCommand:"AProc" :cmd_EveProc :self];
  [tclInterp addCommand:"articulatedProc" :cmd_EveProc :self];
  [tclInterp addCommand:"ArticulatedProc" :cmd_EveProc :self];

  [tclInterp addCommand:"wwSet" :cmd_WWSet :self];
  [tclInterp addCommand:"eSet" :cmd_WWSet :self];
  [tclInterp addCommand:"modelSet" :cmd_WWSet :self];

  [tclInterp addCommand:"ApplyToCTM" :cmd_ApplyToCTM :self];
  [tclInterp addCommand:"applyToCTM" :cmd_ApplyToCTM :self];

  [tclInterp addCommand:"startShape" :cmd_StartShape :self];
  [tclInterp addCommand:"startRootShape" :cmd_StartRootShape :self];
  [tclInterp addCommand:"endShape" :cmd_RiAttributeEnd :self];
  [tclInterp addCommand:"endShape" :cmd_EndShape :self];
  [tclInterp addCommand:"installRootShape" :cmd_InstallRootShape :self];
  [tclInterp addCommand:"startLight" :cmd_StartLight :self];
  [tclInterp addCommand:"startAmbientLight" :cmd_StartAmbientLight :self];
  [tclInterp addCommand:"startDistantLight" :cmd_StartDistantLight :self];
  [tclInterp addCommand:"startPointLight" :cmd_StartPointLight :self];
  [tclInterp addCommand:"startSpotLight" :cmd_StartSpotLight :self];
  [tclInterp addCommand:"endLight" :cmd_RiAttributeEnd :self];

  [tclInterp addCommand:"updateView" :cmd_updateView :self];
  [tclInterp addCommand:"display" :cmd_updateView :self];
  [tclInterp addCommand:"synchWithScene" :cmd_synchWithScene :self];
  [tclInterp addCommand:"synchWithSceneInvisibly" :cmd_synchWithSceneInvisibly :self];
  [tclInterp addCommand:"camera" :cmd_camera :self];

  [tclInterp addCommand:"treatAttributeBeginLikeStartShape" :cmd_TreatAttributeBeginLikeStartShape :self];
  [tclInterp addCommand:"treatTransformBeginLikeAttributeBegin" :cmd_TreatTransformBeginLikeAttributeBegin :self];
  [tclInterp addCommand:"applyShadersDirectlyToCurrentShape" :cmd_ApplyShadersDirectlyToCurrentShape :self];

  // compound commands go here...
  [tclInterp addCommand:"WW3DText" :cmd_WW3DText :self];
  [tclInterp addCommand:"WW3DSquishySphere" :cmd_WW3DSquishySphere :self];

  evaluatingEveCommand = 0;
  tmpRIBCommand = nil;

  return self;
}

- init
{
  [super init];

  tclInterp = [[WWInterp alloc] init];
  [tclInterp setRunTime:self];

  // do this first, pal...
  sceneIncr = 1;

  [self initWWEveParser];

  eveProcList = [[List alloc] init];
  sampleGeneratorInfoList = [[List alloc] init];
  currentSampleGeneratorInfo = nil;

  rib_var_list = list_open(1);
  rib_parm_list = list_open(1);
  rib_light_list = list_open(1);
  rib_object_list = list_open(1);
  currentShape = rootShape = nil;
  ignoreColors = ignoreLights = ignoreShaders = NO;
  ignoreShadingRate = YES;
  rootShapeInUse = NO;
  firmTransforms = NO;
  treatAttributeBeginLikeStartShape = YES;
  treatTransformBeginLikeAttributeBegin = NO;
  applyShadersDirectlyToCurrentShape = YES;
  evaluatingEveProc = NO;
  riBegun = NO;

  uniqueTag = 0;
  cmdBufSize = 4096;
  cmdBuf = (char *)NXZoneCalloc([self zone], cmdBufSize, sizeof(char));
  if (!cmdBuf)
  {  return nil;
  }

  statusBufSize = 256;
  statusBuf = (char *)NXZoneCalloc([self zone], statusBufSize, sizeof(char));
  if (!statusBuf)
  {  return nil;
  }

  lastTimesLength = 256;
  lastTimesIndex = 0;
  lastTimes = (float *)malloc(sizeof(float) * lastTimesLength);
  if (!lastTimes)
  {  return nil;
  }

  articulatedVariablesBehaviorList = [[List alloc] init];

  return self;
}

- awake
{
  [super awake];

  // tclInterp should have been archived
  [tclInterp setRunTime:self];

  // WAVE: this should be archived!
  sceneIncr = 1;
  sampleGeneratorInfoList = [[List alloc] init];
  currentSampleGeneratorInfo = nil;

  [self initWWEveParser];

  // eveProcList should have been archived
  // WAVE!!
  // really should synch up internal state of the tcl interp with the eveProcList...
  // this won't be an issue yet, but should be done eventually.
  // also need to think this through for WW3DCamera

  rib_var_list = list_open(1);
  rib_parm_list = list_open(1);
  rib_light_list = list_open(1);
  rib_object_list = list_open(1);
  currentShape = rootShape = nil;
  rootShapeInUse = NO;
  firmTransforms = NO;
  treatTransformBeginLikeAttributeBegin = NO;
  riBegun = NO;

  uniqueTag = 0;
  cmdBufSize = 4096;
  cmdBuf = (char *)malloc(cmdBufSize);
  if (!cmdBuf)
  {  return nil;
  }
  statusBufSize = 256;
  statusBuf = (char *)NXZoneCalloc([self zone], statusBufSize, sizeof(char));
  if (!statusBuf)
  {  return nil;
  }

  // WAVE!  these should be archived...
  sceneIncr = 1;

  lastTimesLength = 256;
  lastTimesIndex = 0;
  lastTimes = (float *)malloc(sizeof(float) * lastTimesLength);
  if (!lastTimes)
  {  return nil;
  }

  articulatedVariablesBehaviorList = [[List alloc] init];

  return self;
}

- free
{

  //NXLogError("freeing WWEveParser %p\n", self); 
  if (!rootShapeInUse)
  {  [rootShape free];
  }
  list_close(rib_var_list);
  list_close(rib_parm_list);
  list_close(rib_light_list);
  list_close(rib_object_list);
  if (errorWindow)  {  /*NXLogError("freeing errorWindow %p\n", errorWindow);*/ [errorWindow free]; }
  if (cmdBuf) { /*NXLogError("freeing cmdBuf %p\n", cmdBuf);*/ NXZoneFree([self zone], cmdBuf); }
  if (statusBuf) { /*NXLogError("freeing statusBuf %p\n", statusBuf);*/ NXZoneFree([self zone], statusBuf); }

  // make sure you free the tcl interp after the rootShape, because
  // EveCommands that get free'd will want to untrace their corresponding
  // tcl variables, and we don't want them sending messages to an already
  // free'd tclInterp
  //NXLogError("freeing tclInterp %p\n", tclInterp); 
  [tclInterp free];

  if (lastTimesLength)  { free(lastTimes); }

  return [super free];
}


- takeFirmTransforms:sender { firmTransforms = [sender intValue]; return self; }
- setFirmTransforms:(BOOL)flag { firmTransforms = flag; return self; }
- (BOOL)firmTransforms { return firmTransforms; }

- loadErrorWindow
{
  id    bundle = [NXBundle bundleForClass: [self class]];
  char  path[MAXPATHLEN + 1];


  if (!bundle) 
  {  NXLogError("No bundle for Class %s - unable to showErrorWindow\n", [self name]);
     return nil;
  }
  if (![bundle getPath:path forResource:"WWEveParserError" ofType:"nib"])
  {  NXLogError("No path for WWEveParserError.nib.\n");
     return nil;
  }
  [NXApp loadNibFile:path owner:self  withNames:NO fromZone:[self zone]];
  //NXLogError ("Loaded %s.\n", path);

  return self;
}



- buildNewShapeHierarchyFromRIBFile:(const char *)filename :(BOOL)closeControlsFlag
{
  char  tmpBuf[1024], *eveFilename = "/tmp/tmp.eve";
  //BOOL  oldFlag = [tclInterp showErrors];


  // blow away anything we loaded from nib files in preparation of new stuff...
  if (closeControlsFlag)
  {  [[well camera] setWorldShape:nil];
     [rootShape free];
     tmpRootShape = rootShape = currentShape = nil;
     [tclInterp unloadControlPanels];
     [[articulatedVariablesBehaviorList makeObjectsPerform:@selector(free)] empty];
     lastTimesIndex = 0;
  }
  else
  {  tmpRootShape = currentShape = nil;
  }

  sprintf(tmpBuf, "render {%s} {%s}", filename, eveFilename);

  [self setRiBegun:YES];
  // the "render" command will show any errors...
  //[tclInterp setShowErrors:NO];
  if ([tclInterp eval:tmpBuf] != TCL_OK)
  {  [self setRiBegun:NO];
     //[tclInterp setShowErrors:oldFlag];
     return nil;
  }
  //[tclInterp setShowErrors:oldFlag];
  [self setRiBegun:NO];

  if (!closeControlsFlag)
  {  return tmpRootShape;
  }

  rootShape = tmpRootShape;
  return rootShape;
}

- buildNewShapeHierarchyFromRIBFile:(const char *)filename
{  return [self buildNewShapeHierarchyFromRIBFile:filename :YES];
}


- showError:(char *)error
{
  char *errorInfo;


  if (!errorWindow)
  {  [self loadErrorWindow];
  }
  [errorInfoText setSel:0 :[errorInfoText textLength]];
  errorInfo = Tcl_GetVar([tclInterp interp], "errorInfo", 0);
  [errorInfoText replaceSel:errorInfo];
  [errorWindow center];
  [errorWindow makeKeyAndOrderFront:self];

  // should have a button on the window to let them go to the line where the error is...
  // need to pull out the line number and file from the error
  // [[Application workspace] openFile:fileName onHost:"" atTrueLine:lineNumber];

  return self;
}

- buildNewShapeHierarchyFromEveFile:(const char *)filename :(BOOL)closeControlsFlag
{
  char  tmpBuf[1024];
  //BOOL  oldFlag = [tclInterp showErrors];


  if (closeControlsFlag)
  {  [[well camera] setWorldShape:nil];
     [rootShape free];
     tmpRootShape = rootShape = currentShape = nil;
     [tclInterp unloadControlPanels];
     [[articulatedVariablesBehaviorList makeObjectsPerform:@selector(free)] empty];
     lastTimesIndex = 0;
  }
  else
  {  tmpRootShape = currentShape = nil;
  }

  sprintf(tmpBuf, "render {%s} {}", filename);

  [self setRiBegun:YES];
  // the "render" command will show any errors...
  //[tclInterp setShowErrors:NO];
  if ([tclInterp eval:tmpBuf] != TCL_OK)
  {   [self setRiBegun:NO];
     //[tclInterp setShowErrors:oldFlag];
     return nil;
  }
  //[tclInterp setShowErrors:oldFlag];
  [self setRiBegun:NO];

  if (!closeControlsFlag)
  {  return tmpRootShape;
  }

  rootShape = tmpRootShape;
  return rootShape;
}

- buildNewShapeHierarchyFromEveFile:(const char *)filename
{  return [self buildNewShapeHierarchyFromEveFile:filename :YES];
}


- evaluateEveFile:(const char *)filename
{
  char  tmpBuf[MAXPATHLEN + 12], *retBuf;
  int   ret;
  //BOOL  oldFlag = [tclInterp showErrors];


  sprintf(tmpBuf, "source %s", filename);
  //[tclInterp setShowErrors:NO];
  retBuf = [tclInterp eval:tmpBuf :&ret];
  if (ret != TCL_OK)
  {  [self showError:retBuf];
     if (retBuf) { free(retBuf); }
     //[tclInterp setShowErrors:oldFlag];
     return nil;
  }
  //[tclInterp setShowErrors:oldFlag];

  if (retBuf) { free(retBuf); }
  return self;
}

- closeErrorWindow:sender
{
  [errorWindow close];

  return self;
}

- evaluateArticulatedVariablesBehaviorAt:(float)currentTime
{
   int   i, howMany = [articulatedVariablesBehaviorList count];
   char  *originalUValue = NULL;


   // should check and see if there's a variable "u" in the current context.
   // if there is, we should save the value, and restore it at the end.
   originalUValue = [tclInterp getVar:"u"];

   // okay, now tell all the variables to behave
   for (i = 0; i < howMany; i++)
   {  [[articulatedVariablesBehaviorList objectAt:i] evaluateSelfAtTime:currentTime];
   }

   // okay, restore old u value if there was one.
   if (originalUValue)
   {  [tclInterp setVar:"u" toValue:originalUValue];
   }

   return self;
}

- addTimeToLastTimes:(float)currentTime
{
   lastTimesIndex++; 
   while (lastTimesLength <= lastTimesIndex)
   {  lastTimesLength *= 2; 
      lastTimes = (float *)realloc(lastTimes, (sizeof(float) * lastTimesLength));
   }
   lastTimes[lastTimesIndex] = currentTime;
   return self;
}

- setCurrentTime:(float)currentTime
{
   int    j;
   BOOL   alreadyEvaluatedAtTime = NO;


   // execute all articulated variable behaviors for this point 
   //NXLogError("current scene time is %f\n", currentTime);

   if ([[self articulatedVariablesBehaviorList] count])
   { j = 0;
     while ((!alreadyEvaluatedAtTime) && (j <= lastTimesIndex))
     {  if (lastTimes[j] == currentTime)
	{  alreadyEvaluatedAtTime = YES;  
	}
        else
        {  j++;
        }
     }
     if (!alreadyEvaluatedAtTime)
     {  [self evaluateArticulatedVariablesBehaviorAt:currentTime];
        [self addTimeToLastTimes:currentTime];
     }
   }

   return self;
}

- currentShape { return currentShape; }
- setCurrentShape:newShape { currentShape = newShape; return self; }

- (BOOL)rootShapeInUse { return rootShapeInUse; }
- setRootShapeInUse:(BOOL)flag { rootShapeInUse = flag; return self; }

- (BOOL)frozen { return frozen; }
- setFrozen:(BOOL)flag { frozen = flag; return self; }

- rootShape { return rootShape; }
- setRootShape:newShape 
{ 
  if (!rootShapeInUse)
  {  [rootShape free];
  }
  rootShape = newShape; 
  return self; 
}

- tmpRootShape { return tmpRootShape; }
- setTmpRootShape:newShape 
{ 
  tmpRootShape = newShape; 
  return self; 
}

- incrementEveCommandCounter { evaluatingEveCommand++; return self; }
- decrementEveCommandCounter
{ evaluatingEveCommand--; 
  if (evaluatingEveCommand < 0)
  {  NXLogError("warning: evaluatingEveCommand went below zero (%d)\n", evaluatingEveCommand);
     evaluatingEveCommand = 0;
     tmpRIBCommand = nil;
  }
  return self; 
}

- evaluateEveCommand:(char *)cmd
{
  BOOL  tmpFlag;
  id    theRIBCommand;
  int   ret;


  // if the first arg of the cmd is an aproc, we need to malloc up a
  // new RIBCommandList, stick it in tmRIBCommand and then evaluate the
  // cmd.

  if (!evaluatingEveCommand)  // first level of evaluation...
  {  tmpRIBCommand = nil;
  }
  [self incrementEveCommandCounter];
  tmpFlag = [self riBegun];
  [self setRiBegun:YES];

  //[tclInterp eval:cmd];
  // I know, I know - this is gross that I'm doing a global eval...
  ret = [tclInterp globalEval:cmd];

  [self decrementEveCommandCounter];
  [self setRiBegun:tmpFlag];

  if (ret == TCL_OK) // everything was hunk dory
  {  theRIBCommand = tmpRIBCommand;
  }
  else
  {  theRIBCommand = nil;
  }

  [self setTmpRIBCommand:nil];

  return theRIBCommand; 
}

void eveProcTrace(clientData, interp, level, command, cmdProc, cmdClientData, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int level;
char *command;
Tcl_CmdProc *cmdProc;
ClientData cmdClientData;
int argc;
char *argv[];
{
  [(RIBCommandList *)clientData setEveCodeArgc:argc argv:argv];
    
  return ;
}

- evaluateEveProc:(char *)cmd
{
  BOOL       tmpFlag;
  id         theRIBCommand;
  int        ret;
  Tcl_Trace  theTrace;


  // if the first arg of the cmd is an aproc, we need to malloc up a
  // new RIBCommandList, stick it in tmRIBCommand and then evaluate the
  // cmd.

  if (!cmd)  // first level of evaluation...
  {  NXLogError("You asked me to evaluate a NULL EveProc!\n");
     return nil;
  }
  if (evaluatingEveCommand && evaluatingEveProc)  // first level of evaluation...
  {  NXLogError("You cannot nest calls to EveCmd or EveProc inside an EveProc call!\n");
     return nil;
  }
  tmpRIBCommand = [[RIBCommandList alloc] init];
  evaluatingEveProc = YES;
  [self incrementEveCommandCounter];
  tmpFlag = [self riBegun];
  [self setRiBegun:YES];

  // okay, so we need to do a few things here.
  // we need to install a trace to stick the fully closed args of this into the RIBCommandList
  // we also want to trap any calls to "global" and return an error there...
  // actually, we can do both in the trace routine...
  // actually, that's not a great idea...

  // note: I'm being evil here - *wave* wrote Tcl_Level()...

  theTrace = Tcl_CreateTrace([tclInterp interp], 
                             ((int)evil_Tcl_Level_written_by_wave([tclInterp interp]) + 1), 
                             (Tcl_CmdTraceProc *)eveProcTrace, tmpRIBCommand);
  ret = [tclInterp globalEval:cmd];
  Tcl_DeleteTrace([tclInterp interp], theTrace);

  [self decrementEveCommandCounter];
  evaluatingEveProc = NO;
  [self setRiBegun:tmpFlag];
  
  if (ret == TCL_OK) // everything was hunk dory
  {  theRIBCommand = tmpRIBCommand;
  }
  else
  {  theRIBCommand = nil;
  }

  [self setTmpRIBCommand:nil];

  return theRIBCommand; 
}

- setRiBegun:(BOOL)flag  {  riBegun = flag; return self; }
- (BOOL)riBegun { return riBegun; }

////////////////////////////////////////////////////////////
- setIgnoreColors:sender
{
  ignoreColors = [sender intValue];
  return self;
}
- (BOOL)ignoreColors { return ignoreColors; }

- setIgnoreShadingRate:sender
{
  ignoreShadingRate = [sender intValue];
  return self;
}
- (BOOL)ignoreShadingRate { return ignoreShadingRate; }

- setIgnoreShaders:sender
{
  ignoreShaders = [sender intValue];
  return self;
}
- (BOOL)ignoreShaders { return ignoreShaders; }

- setIgnoreLights:sender
{
  ignoreLights = [sender intValue];
  return self;
}
- (BOOL)ignoreLights { return ignoreLights; }

- tclInterp { return tclInterp; }

- (int)uniqueTag { return uniqueTag++; }

- setTmpRIBCommand:newRIBCommand 
{  //NXLogError("tmpRIBCommand is a <%s>\n", [tmpRIBCommand name]);
   if (!newRIBCommand)
   {  // if this is nil, we want to reset things and get out
      tmpRIBCommand = nil;
   }
   else
   {  if (tmpRIBCommand && [tmpRIBCommand respondsTo:@selector(addObject:)])
      {  // it's a RIBCommandList, don't blow it away, just add to it... 
         [tmpRIBCommand addObject:newRIBCommand];
      }
      else
      {  tmpRIBCommand = newRIBCommand; 
      }
   }
   //NXLogError("\tnow it is a <%s>\n", [tmpRIBCommand name]);
   return self; 
}
- tmpRIBCommand { return tmpRIBCommand; }

- (BOOL)evaluatingEveCommand { return (BOOL)evaluatingEveCommand; }

- (BOOL)evaluatingEveProc { return (BOOL)evaluatingEveProc; }

- setEvaluatingEveProc:(BOOL)newFlag
{
  evaluatingEveProc = newFlag;
  if (!evaluatingEveProc)
  {  [self setTmpRIBCommand:nil];  
  }
  return self;
}


//
//
- (BOOL)treatAttributeBeginLikeStartShape { return treatAttributeBeginLikeStartShape; }

- setTreatAttributeBeginLikeStartShape:(BOOL)flag 
{  treatAttributeBeginLikeStartShape = flag; 
   return self; 
}

- takeTreatAttributeBeginLikeStartShape:sender 
{  treatAttributeBeginLikeStartShape = (BOOL)[sender intValue]; 
   return self; 
}


//
//
- (BOOL)treatTransformBeginLikeAttributeBegin { return treatTransformBeginLikeAttributeBegin; }

- setTreatTransformBeginLikeAttributeBegin:(BOOL)flag 
{  treatTransformBeginLikeAttributeBegin = flag; 
   return self; 
}

- takeTreatTransformBeginLikeAttributeBegin:sender 
{  treatTransformBeginLikeAttributeBegin = (BOOL)[sender intValue]; 
   return self; 
}


- (BOOL)applyShadersDirectlyToCurrentShape { return applyShadersDirectlyToCurrentShape; }

- setApplyShadersDirectlyToCurrentShape:(BOOL)flag 
{  applyShadersDirectlyToCurrentShape = flag; 
   return self; 
}

- takeApplyShadersDirectlyToCurrentShape:sender; 
{  applyShadersDirectlyToCurrentShape = (BOOL)[sender intValue]; 
   return self; 
}


- setSceneClock:newSceneClock { sceneClock = newSceneClock; return self; }
- sceneClock { return sceneClock; }
- setTicksPerSecond:(float)newTicksPerSecond
{
   char  buf[128];


   sprintf(buf, "%f", newTicksPerSecond);
   // this is probably bad; it's setting a new trace each time...
   //[[self tclInterp] setVar2:"scene" :"ticksPerSecond" toReadOnlyValue:buf];
   //[[self tclInterp] setVar:"ticksPerSecond" toReadOnlyValue:buf];
   [[self tclInterp] setVar2:"scene" :"ticksPerSecond" toValue:buf];
   [[self tclInterp] setVar:"ticksPerSecond" toValue:buf];
   return self;
}

// boy, this is a hack...
- setViewToUpdate:aView { viewToUpdate = aView; return self; }
- updateView { [viewToUpdate display]; return self; }

- camera { return viewToUpdate; }

- synchViewWithSceneClock 
{ 
   [well synchCameraToSceneClock];
   //[viewToUpdate display]; 
   return self; 
}

- setWell:aWell { well = aWell; return self; }
- installRootShapeInWell 
{ 
   if (tmpRootShape) 
   {  [well setWorldShape:tmpRootShape]; 
      rootShape = tmpRootShape;
      [self updateView];
      return self;
   } 
   return nil; 
}

- setStatusText:newStatusText { statusText = newStatusText; return self; }
- statusText { return statusText; }

- (const char *)currentSampleGeneratorName 
{ 
  if (currentSampleGeneratorInfo)
  {  return [currentSampleGeneratorInfo name];
  }
  return NULL;
}

- (float)currentSampleWeight 
{ 
  if (currentSampleGeneratorInfo)
  {  return [currentSampleGeneratorInfo weight];
  }
  return 1.0;
}

- registerCurrentSampleGeneratorName:(const char *)newCurrentSampleGeneratorName weight:(float)weight
{
   // need to make sure we don't already have one named this
   BOOL  foundIt = NO;
   id    info = nil;
   int   i = 0, 
         howMany = [sampleGeneratorInfoList count];


   if (!newCurrentSampleGeneratorName) // don't allow NULL-named ones
   {  return nil;
   }

   // need to look in our sampleGeneratorInfoList and see if we
   // already know about this guy.  If so, change his weight but leave him alone
   while (!foundIt && (i < howMany))
   {  info = [sampleGeneratorInfoList objectAt:i];
      if (!strcmp(newCurrentSampleGeneratorName, [info name]))
      {  // got it!
         foundIt = YES;
         [info setWeight:weight];
      }
      i++;
   }
   if (!foundIt)
   {  // okay, cons a new one up.
      info = [[[WWSampleGeneratorInfo alloc] init] setName:newCurrentSampleGeneratorName weight:weight];
      [sampleGeneratorInfoList addObject:info];
   }
   return self;
}


- setCurrentSampleGeneratorName:(const char *)newCurrentSampleGeneratorName
{  
   BOOL  foundIt = NO;
   int   i = 0, 
         howMany = [sampleGeneratorInfoList count];


   if (!newCurrentSampleGeneratorName) // if the new one is NULL, that's easy...
   {  currentSampleGeneratorInfo = nil;
      return self;
   }

   // need to look in our sampleGeneratorInfoList and see if we
   // already know about this guy.  If so, swap him in, otherwise cons up a
   // new one, put it in the list with a default weight, and make that current
   while (!foundIt && (i < howMany))
   {  currentSampleGeneratorInfo = [sampleGeneratorInfoList objectAt:i];
      if (!strcmp(newCurrentSampleGeneratorName, [currentSampleGeneratorInfo name]))
      {  // got it!
         foundIt = YES;
      }
      i++;
   }
   if (!foundIt)
   {  // okay, cons a new one up.
      currentSampleGeneratorInfo = [[[WWSampleGeneratorInfo alloc] init] setName:newCurrentSampleGeneratorName weight:1.0];
      [sampleGeneratorInfoList addObject:currentSampleGeneratorInfo];
   }
   return self;
}

- articulatedVariablesBehaviorList { return articulatedVariablesBehaviorList; }

- addArticulatedVariableBehavior:newVarBehavior
{
   [articulatedVariablesBehaviorList addObject:newVarBehavior];

   return self;
}

- disableStatusText
{
   tmpStatusText = statusText;
   statusText = nil;
   return self;
}

- reenableStatusText
{
   statusText = tmpStatusText;
   return self;
}



#define typeVectorVersion1 "@"
#define typeValuesVersion1 &tclInterp

#define typeVectorVersion2 "@cccc"
#define typeValuesVersion2 &tclInterp, &ignoreColors, &ignoreLights, &ignoreShaders, \
                   &treatTransformBeginLikeAttributeBegin

#define typeVector "@cccc@"
#define typeValues &tclInterp, &ignoreColors, &ignoreLights, &ignoreShaders, \
                   &treatTransformBeginLikeAttributeBegin, &eveProcList

- read:(NXTypedStream *)stream 
{
   int version;
   [super read:stream];

NX_DURING
   version = NXTypedStreamClassVersion(stream, "WWEveParser");
   if (version == 0) NXReadTypes(stream,"i",&version), version=1;
   if (version == 1)
   {  NXReadTypes(stream, typeVectorVersion1, typeValuesVersion1);
      ignoreShadingRate = YES;
      treatAttributeBeginLikeStartShape = YES;
      treatAttributeBeginLikeStartShape = YES;
   } 
   if (version == 2)
   {  NXReadTypes(stream, typeVectorVersion2, typeValuesVersion2);
      ignoreShadingRate = YES;
      treatAttributeBeginLikeStartShape = YES;
      treatAttributeBeginLikeStartShape = YES;
   } 
   if (version == 3)
   {  NXReadTypes(stream, typeVector, typeValues);
      ignoreShadingRate = YES;
      treatAttributeBeginLikeStartShape = YES;
      treatAttributeBeginLikeStartShape = YES;
   } 
   if (version == 4)
   {  NXReadTypes(stream, typeVector, typeValues);
      NXReadTypes(stream, "c", &ignoreShadingRate);
      treatAttributeBeginLikeStartShape = YES;
      treatAttributeBeginLikeStartShape = YES;
   } 
   if (version == 5)
   {  NXReadTypes(stream, typeVector, typeValues);
      NXReadTypes(stream, "c", &ignoreShadingRate);
      NXReadTypes(stream, "c", &treatAttributeBeginLikeStartShape);
      treatAttributeBeginLikeStartShape = YES;
   } 
   if (version == 6)
   {  NXReadTypes(stream, typeVector, typeValues);
      NXReadTypes(stream, "c", &ignoreShadingRate);
      NXReadTypes(stream, "c", &treatAttributeBeginLikeStartShape);
      NXReadTypes(stream, "c", &applyShadersDirectlyToCurrentShape);
   } 
NX_HANDLER
   NXLogError("in read: %s, exception [%d] raised.\n", 
                 [[self class] name], NXLocalHandler.code);
   return nil;
NX_ENDHANDLER
   return self;
}

- write:(NXTypedStream *)stream 
{
   [super write:stream];

   NXWriteTypes(stream, typeVector, typeValues);
   NXWriteTypes(stream, "c", &ignoreShadingRate);
   NXWriteTypes(stream, "c", &treatAttributeBeginLikeStartShape);
   NXWriteTypes(stream, "c", &applyShadersDirectlyToCurrentShape);

   return self;
}


@end
